diff --git a/.changes/v1.14/UPGRADE NOTES-20250814-162650.yaml b/.changes/v1.14/UPGRADE NOTES-20250814-162650.yaml new file mode 100644 index 000000000000..17baa54cca2e --- /dev/null +++ b/.changes/v1.14/UPGRADE NOTES-20250814-162650.yaml @@ -0,0 +1,5 @@ +kind: UPGRADE NOTES +body: 'The parallelism of Terraform operations within container runtimes may be reduced depending on the CPU bandwidth limit setting.' +time: 2025-08-14T16:26:50.569878+02:00 +custom: + Issue: "37436" diff --git a/.changes/v1.14/UPGRADE NOTES-20250814-162752.yaml b/.changes/v1.14/UPGRADE NOTES-20250814-162752.yaml new file mode 100644 index 000000000000..c42a78470ce1 --- /dev/null +++ b/.changes/v1.14/UPGRADE NOTES-20250814-162752.yaml @@ -0,0 +1,5 @@ +kind: UPGRADE NOTES +body: 'Building Terraform 1.14 requires macOS Monterey or later (due to being built on Go 1.25 which imposes these requirements)' +time: 2025-08-14T16:27:52.659896+02:00 +custom: + Issue: "37436" diff --git a/.go-version b/.go-version index 6521720b4145..5e2b95002760 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.24.5 +1.25 diff --git a/docs/plugin-protocol/tfplugin6.proto b/docs/plugin-protocol/tfplugin6.proto index 92a565002269..364dd6e7ac3a 100644 --- a/docs/plugin-protocol/tfplugin6.proto +++ b/docs/plugin-protocol/tfplugin6.proto @@ -425,6 +425,11 @@ service Provider { // ConfigureStateStore configures the state store, such as S3 connection in the context of already configured provider rpc ConfigureStateStore(ConfigureStateStore.Request) returns (ConfigureStateStore.Response); + // ReadStateBytes streams byte chunks of a given state file from a state store + rpc ReadStateBytes(ReadStateBytes.Request) returns (stream ReadStateBytes.Response); + // WriteStateBytes streams byte chunks of a given state file into a state store + rpc WriteStateBytes(stream WriteStateBytes.RequestChunk) returns (WriteStateBytes.Response); + // GetStates returns a list of all states (i.e. CE workspaces) managed by a given state store rpc GetStates(GetStates.Request) returns (GetStates.Response); // DeleteState instructs a given state store to delete a specific state (i.e. a CE workspace) @@ -918,7 +923,6 @@ message ValidateListResourceConfig { } } - message ValidateStateStore { message Request { string type_name = 1; @@ -939,6 +943,39 @@ message ConfigureStateStore { } } +message ReadStateBytes { + message Request { + string type_name = 1; + string state_id = 2; + } + message Response { + bytes bytes = 1; + int64 total_length = 2; + StateRange range = 3; + repeated Diagnostic diagnostics = 4; + } +} + +message WriteStateBytes { + message RequestChunk { + // TODO: Can we decouple this outside of the stream? + string type_name = 1; + string state_id = 3; + + bytes bytes = 2; + int64 total_length = 4; + StateRange range = 5; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message StateRange { + int64 start = 1; + int64 end = 2; +} + message GetStates { message Request { string type_name = 1; diff --git a/go.mod b/go.mod index 07e81397f4f7..d375fdf6e0f4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform -go 1.24.5 +go 1.25 godebug winsymlink=0 diff --git a/internal/backend/pluggable/pluggable.go b/internal/backend/pluggable/pluggable.go index 2b7fd8f98d33..920016cbcff7 100644 --- a/internal/backend/pluggable/pluggable.go +++ b/internal/backend/pluggable/pluggable.go @@ -68,6 +68,15 @@ func (p *Pluggable) ConfigSchema() *configschema.Block { return val.Body } +// ProviderSchema returns the schema for the provider implementing the state store. +// +// This isn't part of the backend.Backend interface but is needed in calling code. +// When it's used the backend.Backend will need to be cast to a Pluggable. +func (p *Pluggable) ProviderSchema() *configschema.Block { + schemaResp := p.provider.GetProviderSchema() + return schemaResp.Provider.Body +} + // PrepareConfig validates configuration for the state store in // the state storage provider. The configuration sent from Terraform core // will not include any values from environment variables; it is the diff --git a/internal/backend/remote-state/azure/go.mod b/internal/backend/remote-state/azure/go.mod index f1d42da2b6fb..1dcd6c42036f 100644 --- a/internal/backend/remote-state/azure/go.mod +++ b/internal/backend/remote-state/azure/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/azure -go 1.24.5 +go 1.25 require ( github.com/hashicorp/go-azure-helpers v0.72.0 diff --git a/internal/backend/remote-state/consul/go.mod b/internal/backend/remote-state/consul/go.mod index a6e698e7d096..2f17f4918689 100644 --- a/internal/backend/remote-state/consul/go.mod +++ b/internal/backend/remote-state/consul/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/consul -go 1.24.5 +go 1.25 require ( github.com/hashicorp/consul/api v1.32.1 diff --git a/internal/backend/remote-state/cos/go.mod b/internal/backend/remote-state/cos/go.mod index 9826dd704f50..dde5c75a8fea 100644 --- a/internal/backend/remote-state/cos/go.mod +++ b/internal/backend/remote-state/cos/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/cos -go 1.24.5 +go 1.25 require ( github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000 diff --git a/internal/backend/remote-state/gcs/go.mod b/internal/backend/remote-state/gcs/go.mod index cf9c8d163b89..d245f8132fb8 100644 --- a/internal/backend/remote-state/gcs/go.mod +++ b/internal/backend/remote-state/gcs/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/gcs -go 1.24.5 +go 1.25 require ( cloud.google.com/go/kms v1.15.5 diff --git a/internal/backend/remote-state/kubernetes/go.mod b/internal/backend/remote-state/kubernetes/go.mod index 84c23c3dbf38..1b297122bdca 100644 --- a/internal/backend/remote-state/kubernetes/go.mod +++ b/internal/backend/remote-state/kubernetes/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/kubernetes -go 1.24.5 +go 1.25 require ( github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000 diff --git a/internal/backend/remote-state/oci/go.mod b/internal/backend/remote-state/oci/go.mod index e7707ebfc360..e732c9df21cd 100644 --- a/internal/backend/remote-state/oci/go.mod +++ b/internal/backend/remote-state/oci/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/oci -go 1.24.5 +go 1.25 require ( github.com/google/go-cmp v0.7.0 diff --git a/internal/backend/remote-state/oss/go.mod b/internal/backend/remote-state/oss/go.mod index 75fac8e1fe7d..22a6d4828790 100644 --- a/internal/backend/remote-state/oss/go.mod +++ b/internal/backend/remote-state/oss/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/oss -go 1.24.5 +go 1.25 require ( github.com/aliyun/alibaba-cloud-sdk-go v1.61.1501 diff --git a/internal/backend/remote-state/pg/go.mod b/internal/backend/remote-state/pg/go.mod index d38e0307de49..ea3e3f7c114a 100644 --- a/internal/backend/remote-state/pg/go.mod +++ b/internal/backend/remote-state/pg/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/pg -go 1.24.5 +go 1.25 require ( github.com/hashicorp/go-uuid v1.0.3 diff --git a/internal/backend/remote-state/s3/go.mod b/internal/backend/remote-state/s3/go.mod index dbe60197b5d0..b3651d1a996a 100644 --- a/internal/backend/remote-state/s3/go.mod +++ b/internal/backend/remote-state/s3/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/s3 -go 1.24.5 +go 1.25 require ( github.com/aws/aws-sdk-go-v2 v1.36.0 diff --git a/internal/builtin/providers/terraform/provider.go b/internal/builtin/providers/terraform/provider.go index b96f1df3ad01..c4330cda51e9 100644 --- a/internal/builtin/providers/terraform/provider.go +++ b/internal/builtin/providers/terraform/provider.go @@ -291,6 +291,18 @@ func (p *Provider) ConfigureStateStore(req providers.ConfigureStateStoreRequest) return resp } +func (p *Provider) ReadStateBytes(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + var resp providers.ReadStateBytesResponse + resp.Diagnostics.Append(fmt.Errorf("unsupported state store type %q", req.TypeName)) + return resp +} + +func (p *Provider) WriteStateBytes(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + var resp providers.WriteStateBytesResponse + resp.Diagnostics.Append(fmt.Errorf("unsupported state store type %q", req.TypeName)) + return resp +} + func (p *Provider) GetStates(req providers.GetStatesRequest) providers.GetStatesResponse { var resp providers.GetStatesResponse resp.Diagnostics.Append(fmt.Errorf("unsupported state store type %q", req.TypeName)) diff --git a/internal/command/arguments/init.go b/internal/command/arguments/init.go index 6bb74473847a..91b2846b7456 100644 --- a/internal/command/arguments/init.go +++ b/internal/command/arguments/init.go @@ -78,6 +78,10 @@ type Init struct { // TODO(SarahFrench/radeksimko): Remove this once the feature is no longer // experimental EnablePssExperiment bool + + // CreateDefaultWorkspace indicates whether the default workspace should be created by + // Terraform when initializing a state store for the first time. + CreateDefaultWorkspace bool } // ParseInit processes CLI arguments, returning an Init value and errors. @@ -111,7 +115,7 @@ func ParseInit(args []string) (*Init, tfdiags.Diagnostics) { cmdFlags.BoolVar(&init.Json, "json", false, "json") cmdFlags.Var(&init.BackendConfig, "backend-config", "") cmdFlags.Var(&init.PluginPath, "plugin-dir", "plugin directory") - + cmdFlags.BoolVar(&init.CreateDefaultWorkspace, "create-default-workspace", true, "when -input=false, use this flag to block creation of the default workspace") // Used for enabling experimental code that's invoked before configuration is parsed. cmdFlags.BoolVar(&init.EnablePssExperiment, "enable-pluggable-state-storage-experiment", false, "Enable the pluggable state storage experiment") @@ -139,6 +143,14 @@ func ParseInit(args []string) (*Init, tfdiags.Diagnostics) { )) } + if init.InputEnabled && !init.CreateDefaultWorkspace { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Warning, + "Invalid init options", + "The flag -create-default-workspace=false is ignored when Terraform is configured to ask users for input. Instead, add -input=false or remove the -create-default-workspace flag", + )) + } + init.Args = cmdFlags.Args() backendFlagSet := FlagIsSet(cmdFlags, "backend") diff --git a/internal/command/arguments/init_test.go b/internal/command/arguments/init_test.go index 93e13b7b6281..2c78e97254fb 100644 --- a/internal/command/arguments/init_test.go +++ b/internal/command/arguments/init_test.go @@ -40,10 +40,11 @@ func TestParseInit_basicValid(t *testing.T) { FlagName: "-backend-config", Items: &flagNameValue, }, - Vars: &Vars{}, - InputEnabled: true, - CompactWarnings: false, - TargetFlags: nil, + Vars: &Vars{}, + InputEnabled: true, + CompactWarnings: false, + TargetFlags: nil, + CreateDefaultWorkspace: true, }, }, "setting multiple options": { @@ -72,11 +73,12 @@ func TestParseInit_basicValid(t *testing.T) { FlagName: "-backend-config", Items: &flagNameValue, }, - Vars: &Vars{}, - InputEnabled: true, - Args: []string{}, - CompactWarnings: true, - TargetFlags: nil, + Vars: &Vars{}, + InputEnabled: true, + Args: []string{}, + CompactWarnings: true, + TargetFlags: nil, + CreateDefaultWorkspace: true, }, }, "with cloud option": { @@ -101,11 +103,12 @@ func TestParseInit_basicValid(t *testing.T) { FlagName: "-backend-config", Items: &[]FlagNameValue{{Name: "-backend-config", Value: "backend.config"}}, }, - Vars: &Vars{}, - InputEnabled: false, - Args: []string{}, - CompactWarnings: false, - TargetFlags: []string{"foo_bar.baz"}, + Vars: &Vars{}, + InputEnabled: false, + Args: []string{}, + CompactWarnings: false, + TargetFlags: []string{"foo_bar.baz"}, + CreateDefaultWorkspace: true, }, }, } diff --git a/internal/command/cloud_test.go b/internal/command/cloud_test.go index 3661e4b98b64..cf59acfbdf5d 100644 --- a/internal/command/cloud_test.go +++ b/internal/command/cloud_test.go @@ -135,7 +135,7 @@ func TestCloud_withBackendConfig(t *testing.T) { // Initialize the backend ic := &InitCommand{ - Meta{ + Meta: Meta{ Ui: ui, View: view, testingOverrides: metaOverridesForProvider(testProvider()), diff --git a/internal/command/init.go b/internal/command/init.go index 3618f6f287b4..4921847090bb 100644 --- a/internal/command/init.go +++ b/internal/command/init.go @@ -28,8 +28,10 @@ import ( "github.com/hashicorp/terraform/internal/command/views" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/configschema" + "github.com/hashicorp/terraform/internal/depsfile" "github.com/hashicorp/terraform/internal/didyoumean" "github.com/hashicorp/terraform/internal/getproviders" + "github.com/hashicorp/terraform/internal/getproviders/providerreqs" "github.com/hashicorp/terraform/internal/providercache" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/tfdiags" @@ -40,6 +42,8 @@ import ( // module and clones it to the working directory. type InitCommand struct { Meta + + incompleteProviders []string } func (c *InitCommand) Run(args []string) int { @@ -65,7 +69,7 @@ func (c *InitCommand) Run(args []string) int { } if c.Meta.AllowExperimentalFeatures && initArgs.EnablePssExperiment { // TODO(SarahFrench/radeksimko): Remove forked init logic once feature is no longer experimental - panic("This experiment is not available yet") + return c.runPssInit(initArgs, view) } else { return c.run(initArgs, view) } @@ -155,7 +159,11 @@ func (c *InitCommand) initCloud(ctx context.Context, root *configs.Module, extra return back, true, diags } -func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, extraConfig arguments.FlagNameValueSlice, viewType arguments.ViewType, view views.Init) (be backend.Backend, output bool, diags tfdiags.Diagnostics) { +func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, initArgs *arguments.Init, locks *depsfile.Locks, view views.Init) (be backend.Backend, output bool, diags tfdiags.Diagnostics) { + // Temporary vars to account for refactoring the method's parameters + extraConfig := initArgs.BackendConfig + viewType := initArgs.ViewType + ctx, span := tracer.Start(ctx, "initialize backend") _ = ctx // prevent staticcheck from complaining to avoid a maintenance hazard of having the wrong ctx in scope here defer span.End() @@ -183,34 +191,9 @@ func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, ext return nil, true, diags case root.StateStore != nil: // state_store config present - // Access provider factories - ctxOpts, err := c.contextOpts() - if err != nil { - diags = diags.Append(err) - return nil, true, diags - } - - if root.StateStore.ProviderAddr.IsZero() { - // This should not happen; this data is populated when parsing config, - // even for builtin providers - panic(fmt.Sprintf("unknown provider while beginning to initialize state store %q from provider %q", - root.StateStore.Type, - root.StateStore.Provider.Name)) - } - - var exists bool - factory, exists := ctxOpts.Providers[root.StateStore.ProviderAddr] - if !exists { - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Provider unavailable", - Detail: fmt.Sprintf("The provider %s (%q) is required to initialize the %q state store, but the matching provider factory is missing. This is a bug in Terraform and should be reported.", - root.StateStore.Provider.Name, - root.StateStore.ProviderAddr, - root.StateStore.Type, - ), - Subject: &root.Backend.TypeRange, - }) + factory, fDiags := c.Meta.getStateStoreProviderFactory(root.StateStore) + diags = diags.Append(fDiags) + if fDiags.HasErrors() { return nil, true, diags } @@ -267,11 +250,13 @@ func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, ext } opts = &BackendOpts{ - StateStoreConfig: root.StateStore, - ProviderFactory: factory, - ConfigOverride: configOverride, - Init: true, - ViewType: viewType, + StateStoreConfig: root.StateStore, + Locks: locks, + ProviderFactory: factory, + CreateDefaultWorkspace: initArgs.CreateDefaultWorkspace, + ConfigOverride: configOverride, + Init: true, + ViewType: viewType, } case root.Backend != nil: @@ -307,15 +292,19 @@ func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, ext backendSchema := b.ConfigSchema() backendConfig := root.Backend - backendConfigOverride, overrideDiags := c.backendConfigOverrideBody(extraConfig, backendSchema) - diags = diags.Append(overrideDiags) - if overrideDiags.HasErrors() { - return nil, true, diags + var configOverride hcl.Body + if len(*extraConfig.Items) > 0 { + var overrideDiags tfdiags.Diagnostics + configOverride, overrideDiags = c.backendConfigOverrideBody(extraConfig, backendSchema) + diags = diags.Append(overrideDiags) + if overrideDiags.HasErrors() { + return nil, true, diags + } } opts = &BackendOpts{ BackendConfig: backendConfig, - ConfigOverride: backendConfigOverride, + ConfigOverride: configOverride, Init: true, ViewType: viewType, } @@ -358,8 +347,11 @@ the backend configuration is present and valid. return back, true, diags } -// Load the complete module tree, and fetch any missing providers. -// This method outputs its own Ui. +// getProviders determines what providers are required given configuration and state data. The method downloads any missing providers +// and replaces the contents of the dependency lock file if any changes happen. +// The calling code is expected to have loaded the complete module tree and read the state file, and passes that data into this method. +// +// This method outputs to the provided view. The returned `output` boolean lets calling code know if anything has been rendered via the view. func (c *InitCommand) getProviders(ctx context.Context, config *configs.Config, state *states.State, upgrade bool, pluginDirs []string, flagLockfile string, view views.Init) (output, abort bool, diags tfdiags.Diagnostics) { ctx, span := tracer.Start(ctx, "install providers") defer span.End() @@ -808,6 +800,577 @@ func (c *InitCommand) getProviders(ctx context.Context, config *configs.Config, return true, false, diags } +// getProvidersFromConfig determines what providers are required by the given configuration data. +// The method downloads any missing providers that aren't already downloaded and then returns +// dependency lock data based on the configuration. +// The dependency lock file itself isn't updated here. +func (c *InitCommand) getProvidersFromConfig(ctx context.Context, config *configs.Config, upgrade bool, pluginDirs []string, flagLockfile string, view views.Init) (output bool, resultingLocks *depsfile.Locks, diags tfdiags.Diagnostics) { + ctx, span := tracer.Start(ctx, "install providers from config") + defer span.End() + + // Dev overrides cause the result of "terraform init" to be irrelevant for + // any overridden providers, so we'll warn about it to avoid later + // confusion when Terraform ends up using a different provider than the + // lock file called for. + diags = diags.Append(c.providerDevOverrideInitWarnings()) + + // Collect the provider dependencies from the configuration. + reqs, hclDiags := config.ProviderRequirements() + diags = diags.Append(hclDiags) + if hclDiags.HasErrors() { + return false, nil, diags + } + + for providerAddr := range reqs { + if providerAddr.IsLegacy() { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid legacy provider address", + fmt.Sprintf( + "This configuration or its associated state refers to the unqualified provider %q.\n\nYou must complete the Terraform 0.13 upgrade process before upgrading to later versions.", + providerAddr.Type, + ), + )) + } + } + if diags.HasErrors() { + return false, nil, diags + } + + var inst *providercache.Installer + if len(pluginDirs) == 0 { + // By default we use a source that looks for providers in all of the + // standard locations, possibly customized by the user in CLI config. + inst = c.providerInstaller() + } else { + // If the user passes at least one -plugin-dir then that circumvents + // the usual sources and forces Terraform to consult only the given + // directories. Anything not available in one of those directories + // is not available for installation. + source := c.providerCustomLocalDirectorySource(pluginDirs) + inst = c.providerInstallerCustomSource(source) + + // The default (or configured) search paths are logged earlier, in provider_source.go + // Log that those are being overridden by the `-plugin-dir` command line options + log.Println("[DEBUG] init: overriding provider plugin search paths") + log.Printf("[DEBUG] will search for provider plugins in %s", pluginDirs) + } + + evts := c.prepareInstallerEvents(ctx, reqs, diags, inst, view, views.InitializingProviderPluginFromConfigMessage, views.ReusingPreviousVersionInfo) + ctx = evts.OnContext(ctx) + + mode := providercache.InstallNewProvidersOnly + if upgrade { + if flagLockfile == "readonly" { + diags = diags.Append(fmt.Errorf("The -upgrade flag conflicts with -lockfile=readonly.")) + view.Diagnostics(diags) + return true, nil, diags + } + + mode = providercache.InstallUpgrades + } + + // Previous locks from dep locks file are needed so we don't re-download any providers + previousLocks, moreDiags := c.lockedDependencies() + diags = diags.Append(moreDiags) + if diags.HasErrors() { + return false, nil, diags + } + + // Determine which required providers are already downloaded, and download any + // new providers or newer versions of providers + configLocks, err := inst.EnsureProviderVersions(ctx, previousLocks, reqs, mode) + if ctx.Err() == context.Canceled { + diags = diags.Append(fmt.Errorf("Provider installation was canceled by an interrupt signal.")) + view.Diagnostics(diags) + return true, nil, diags + } + if err != nil { + // The errors captured in "err" should be redundant with what we + // received via the InstallerEvents callbacks above, so we'll + // just return those as long as we have some. + if !diags.HasErrors() { + diags = diags.Append(err) + } + + return true, nil, diags + } + + return true, configLocks, diags +} + +// getProvidersFromState determines what providers are required by the given state data. +// The method downloads any missing providers that aren't already downloaded and then returns +// dependency lock data based on the state. +// The calling code is assumed to have already called getProvidersFromConfig, which is used to +// supply the configLocks argument. +// The dependency lock file itself isn't updated here. +func (c *InitCommand) getProvidersFromState(ctx context.Context, state *states.State, configLocks *depsfile.Locks, upgrade bool, pluginDirs []string, flagLockfile string, view views.Init) (output bool, resultingLocks *depsfile.Locks, diags tfdiags.Diagnostics) { + ctx, span := tracer.Start(ctx, "install providers from state") + defer span.End() + + // Dev overrides cause the result of "terraform init" to be irrelevant for + // any overridden providers, so we'll warn about it to avoid later + // confusion when Terraform ends up using a different provider than the + // lock file called for. + diags = diags.Append(c.providerDevOverrideInitWarnings()) + + if state == nil { + // if there is no state there are no providers to get + return true, depsfile.NewLocks(), nil + } + reqs := state.ProviderRequirements() + + for providerAddr := range reqs { + if providerAddr.IsLegacy() { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid legacy provider address", + fmt.Sprintf( + "This configuration or its associated state refers to the unqualified provider %q.\n\nYou must complete the Terraform 0.13 upgrade process before upgrading to later versions.", + providerAddr.Type, + ), + )) + } + } + if diags.HasErrors() { + return false, nil, diags + } + + // The locks below are used to avoid re-downloading any providers in the + // second download step. + // We combine any locks from the dependency lock file and locks identified + // from the configuration + var moreDiags tfdiags.Diagnostics + previousLocks, moreDiags := c.lockedDependencies() + diags = diags.Append(moreDiags) + if diags.HasErrors() { + return false, nil, diags + } + inProgressLocks := c.mergeLockedDependencies(configLocks, previousLocks) + + var inst *providercache.Installer + if len(pluginDirs) == 0 { + // By default we use a source that looks for providers in all of the + // standard locations, possibly customized by the user in CLI config. + inst = c.providerInstaller() + } else { + // If the user passes at least one -plugin-dir then that circumvents + // the usual sources and forces Terraform to consult only the given + // directories. Anything not available in one of those directories + // is not available for installation. + source := c.providerCustomLocalDirectorySource(pluginDirs) + inst = c.providerInstallerCustomSource(source) + + // The default (or configured) search paths are logged earlier, in provider_source.go + // Log that those are being overridden by the `-plugin-dir` command line options + log.Println("[DEBUG] init: overriding provider plugin search paths") + log.Printf("[DEBUG] will search for provider plugins in %s", pluginDirs) + } + + // Because we're currently just streaming a series of events sequentially + // into the terminal, we're showing only a subset of the events to keep + // things relatively concise. Later it'd be nice to have a progress UI + // where statuses update in-place, but we can't do that as long as we + // are shimming our vt100 output to the legacy console API on Windows. + evts := c.prepareInstallerEvents(ctx, reqs, diags, inst, view, views.InitializingProviderPluginFromStateMessage, views.ReusingVersionIdentifiedFromConfig) + ctx = evts.OnContext(ctx) + + mode := providercache.InstallNewProvidersOnly + + // We don't handle upgrade flags here, i.e. what happens at this point in getProvidersFromConfig: + // > We cannot upgrade a provider used only by the state, as there are no version constraints in state. + // > Given the overlap between providers in the config and state, using the upgrade mode here + // would remove the effects of version constraints from the config. + // > Any validation of CLI flag usage is already done in getProvidersFromConfig + + newLocks, err := inst.EnsureProviderVersions(ctx, inProgressLocks, reqs, mode) + if ctx.Err() == context.Canceled { + diags = diags.Append(fmt.Errorf("Provider installation was canceled by an interrupt signal.")) + view.Diagnostics(diags) + return true, nil, diags + } + if err != nil { + // The errors captured in "err" should be redundant with what we + // received via the InstallerEvents callbacks above, so we'll + // just return those as long as we have some. + if !diags.HasErrors() { + diags = diags.Append(err) + } + + return true, nil, diags + } + + return true, newLocks, diags +} + +// saveDependencyLockFile overwrites the contents of the dependency lock file. +// The calling code is expected to provide the previous locks (if any) and the two sets of locks determined from +// configuration and state data. +func (c *InitCommand) saveDependencyLockFile(previousLocks, configLocks, stateLocks *depsfile.Locks, flagLockfile string, view views.Init) (output bool, diags tfdiags.Diagnostics) { + + // Get the combination of config and state locks + newLocks := c.mergeLockedDependencies(configLocks, stateLocks) + + // If the provider dependencies have changed since the last run then we'll + // say a little about that in case the reader wasn't expecting a change. + // (When we later integrate module dependencies into the lock file we'll + // probably want to refactor this so that we produce one lock-file related + // message for all changes together, but this is here for now just because + // it's the smallest change relative to what came before it, which was + // a hidden JSON file specifically for tracking providers.) + if !newLocks.Equal(previousLocks) { + // if readonly mode + if flagLockfile == "readonly" { + // check if required provider dependencies change + if !newLocks.EqualProviderAddress(previousLocks) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + `Provider dependency changes detected`, + `Changes to the required provider dependencies were detected, but the lock file is read-only. To use and record these requirements, run "terraform init" without the "-lockfile=readonly" flag.`, + )) + return output, diags + } + // suppress updating the file to record any new information it learned, + // such as a hash using a new scheme. + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Warning, + `Provider lock file not updated`, + `Changes to the provider selections were detected, but not saved in the .terraform.lock.hcl file. To record these selections, run "terraform init" without the "-lockfile=readonly" flag.`, + )) + return output, diags + } + // Jump in here and add a warning if any of the providers are incomplete. + if len(c.incompleteProviders) > 0 { + // We don't really care about the order here, we just want the + // output to be deterministic. + sort.Slice(c.incompleteProviders, func(i, j int) bool { + return c.incompleteProviders[i] < c.incompleteProviders[j] + }) + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Warning, + incompleteLockFileInformationHeader, + fmt.Sprintf( + incompleteLockFileInformationBody, + strings.Join(c.incompleteProviders, "\n - "), + getproviders.CurrentPlatform.String()))) + } + if previousLocks.Empty() { + // A change from empty to non-empty is special because it suggests + // we're running "terraform init" for the first time against a + // new configuration. In that case we'll take the opportunity to + // say a little about what the dependency lock file is, for new + // users or those who are upgrading from a previous Terraform + // version that didn't have dependency lock files. + view.Output(views.LockInfo) + output = true + } else { + view.Output(views.DependenciesLockChangesInfo) + output = true + } + lockFileDiags := c.replaceLockedDependencies(newLocks) + diags = diags.Append(lockFileDiags) + } + return output, diags +} + +// prepareInstallerEvents returns an instance of *providercache.InstallerEvents. This struct defines callback functions that will be executed +// when a specific type of event occurs during provider installation. +// The calling code needs to provide a tfdiags.Diagnostics collection, so that provider installation code returns diags to the calling code using closures +func (c *InitCommand) prepareInstallerEvents(ctx context.Context, reqs providerreqs.Requirements, diags tfdiags.Diagnostics, inst *providercache.Installer, view views.Init, initMsg views.InitMessageCode, reuseMsg views.InitMessageCode) *providercache.InstallerEvents { + + // Because we're currently just streaming a series of events sequentially + // into the terminal, we're showing only a subset of the events to keep + // things relatively concise. Later it'd be nice to have a progress UI + // where statuses update in-place, but we can't do that as long as we + // are shimming our vt100 output to the legacy console API on Windows. + events := &providercache.InstallerEvents{ + PendingProviders: func(reqs map[addrs.Provider]getproviders.VersionConstraints) { + view.Output(initMsg) + }, + ProviderAlreadyInstalled: func(provider addrs.Provider, selectedVersion getproviders.Version) { + view.LogInitMessage(views.ProviderAlreadyInstalledMessage, provider.ForDisplay(), selectedVersion) + }, + BuiltInProviderAvailable: func(provider addrs.Provider) { + view.LogInitMessage(views.BuiltInProviderAvailableMessage, provider.ForDisplay()) + }, + BuiltInProviderFailure: func(provider addrs.Provider, err error) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid dependency on built-in provider", + fmt.Sprintf("Cannot use %s: %s.", provider.ForDisplay(), err), + )) + }, + QueryPackagesBegin: func(provider addrs.Provider, versionConstraints getproviders.VersionConstraints, locked bool) { + if locked { + view.LogInitMessage(reuseMsg, provider.ForDisplay()) + } else { + if len(versionConstraints) > 0 { + view.LogInitMessage(views.FindingMatchingVersionMessage, provider.ForDisplay(), getproviders.VersionConstraintsString(versionConstraints)) + } else { + view.LogInitMessage(views.FindingLatestVersionMessage, provider.ForDisplay()) + } + } + }, + LinkFromCacheBegin: func(provider addrs.Provider, version getproviders.Version, cacheRoot string) { + view.LogInitMessage(views.UsingProviderFromCacheDirInfo, provider.ForDisplay(), version) + }, + FetchPackageBegin: func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation) { + view.LogInitMessage(views.InstallingProviderMessage, provider.ForDisplay(), version) + }, + QueryPackagesFailure: func(provider addrs.Provider, err error) { + switch errorTy := err.(type) { + case getproviders.ErrProviderNotFound: + sources := errorTy.Sources + displaySources := make([]string, len(sources)) + for i, source := range sources { + displaySources[i] = fmt.Sprintf(" - %s", source) + } + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to query available provider packages", + fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s\n\n%s", + provider.ForDisplay(), err, strings.Join(displaySources, "\n"), + ), + )) + case getproviders.ErrRegistryProviderNotKnown: + // We might be able to suggest an alternative provider to use + // instead of this one. + suggestion := fmt.Sprintf("\n\nAll modules should specify their required_providers so that external consumers will get the correct providers when using a module. To see which modules are currently depending on %s, run the following command:\n terraform providers", provider.ForDisplay()) + alternative := getproviders.MissingProviderSuggestion(ctx, provider, inst.ProviderSource(), reqs) + if alternative != provider { + suggestion = fmt.Sprintf( + "\n\nDid you intend to use %s? If so, you must specify that source address in each module which requires that provider. To see which modules are currently depending on %s, run the following command:\n terraform providers", + alternative.ForDisplay(), provider.ForDisplay(), + ) + } + + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to query available provider packages", + fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s%s", + provider.ForDisplay(), err, suggestion, + ), + )) + case getproviders.ErrHostNoProviders: + switch { + case errorTy.Hostname == svchost.Hostname("github.com") && !errorTy.HasOtherVersion: + // If a user copies the URL of a GitHub repository into + // the source argument and removes the schema to make it + // provider-address-shaped then that's one way we can end up + // here. We'll use a specialized error message in anticipation + // of that mistake. We only do this if github.com isn't a + // provider registry, to allow for the (admittedly currently + // rather unlikely) possibility that github.com starts being + // a real Terraform provider registry in the future. + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid provider registry host", + fmt.Sprintf("The given source address %q specifies a GitHub repository rather than a Terraform provider. Refer to the documentation of the provider to find the correct source address to use.", + provider.String(), + ), + )) + + case errorTy.HasOtherVersion: + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid provider registry host", + fmt.Sprintf("The host %q given in provider source address %q does not offer a Terraform provider registry that is compatible with this Terraform version, but it may be compatible with a different Terraform version.", + errorTy.Hostname, provider.String(), + ), + )) + + default: + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid provider registry host", + fmt.Sprintf("The host %q given in provider source address %q does not offer a Terraform provider registry.", + errorTy.Hostname, provider.String(), + ), + )) + } + + case getproviders.ErrRequestCanceled: + // We don't attribute cancellation to any particular operation, + // but rather just emit a single general message about it at + // the end, by checking ctx.Err(). + + default: + suggestion := fmt.Sprintf("\n\nTo see which modules are currently depending on %s and what versions are specified, run the following command:\n terraform providers", provider.ForDisplay()) + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to query available provider packages", + fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s%s", + provider.ForDisplay(), err, suggestion, + ), + )) + } + + }, + QueryPackagesWarning: func(provider addrs.Provider, warnings []string) { + displayWarnings := make([]string, len(warnings)) + for i, warning := range warnings { + displayWarnings[i] = fmt.Sprintf("- %s", warning) + } + + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Warning, + "Additional provider information from registry", + fmt.Sprintf("The remote registry returned warnings for %s:\n%s", + provider.String(), + strings.Join(displayWarnings, "\n"), + ), + )) + }, + LinkFromCacheFailure: func(provider addrs.Provider, version getproviders.Version, err error) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to install provider from shared cache", + fmt.Sprintf("Error while importing %s v%s from the shared cache directory: %s.", provider.ForDisplay(), version, err), + )) + }, + FetchPackageFailure: func(provider addrs.Provider, version getproviders.Version, err error) { + const summaryIncompatible = "Incompatible provider version" + switch err := err.(type) { + case getproviders.ErrProtocolNotSupported: + closestAvailable := err.Suggestion + switch { + case closestAvailable == getproviders.UnspecifiedVersion: + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + summaryIncompatible, + fmt.Sprintf(errProviderVersionIncompatible, provider.String()), + )) + case version.GreaterThan(closestAvailable): + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + summaryIncompatible, + fmt.Sprintf(providerProtocolTooNew, provider.ForDisplay(), + version, tfversion.String(), closestAvailable, closestAvailable, + getproviders.VersionConstraintsString(reqs[provider]), + ), + )) + default: // version is less than closestAvailable + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + summaryIncompatible, + fmt.Sprintf(providerProtocolTooOld, provider.ForDisplay(), + version, tfversion.String(), closestAvailable, closestAvailable, + getproviders.VersionConstraintsString(reqs[provider]), + ), + )) + } + case getproviders.ErrPlatformNotSupported: + switch { + case err.MirrorURL != nil: + // If we're installing from a mirror then it may just be + // the mirror lacking the package, rather than it being + // unavailable from upstream. + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + summaryIncompatible, + fmt.Sprintf( + "Your chosen provider mirror at %s does not have a %s v%s package available for your current platform, %s.\n\nProvider releases are separate from Terraform CLI releases, so this provider might not support your current platform. Alternatively, the mirror itself might have only a subset of the plugin packages available in the origin registry, at %s.", + err.MirrorURL, err.Provider, err.Version, err.Platform, + err.Provider.Hostname, + ), + )) + default: + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + summaryIncompatible, + fmt.Sprintf( + "Provider %s v%s does not have a package available for your current platform, %s.\n\nProvider releases are separate from Terraform CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.", + err.Provider, err.Version, err.Platform, + ), + )) + } + + case getproviders.ErrRequestCanceled: + // We don't attribute cancellation to any particular operation, + // but rather just emit a single general message about it at + // the end, by checking ctx.Err(). + + default: + // We can potentially end up in here under cancellation too, + // in spite of our getproviders.ErrRequestCanceled case above, + // because not all of the outgoing requests we do under the + // "fetch package" banner are source metadata requests. + // In that case we will emit a redundant error here about + // the request being cancelled, but we'll still detect it + // as a cancellation after the installer returns and do the + // normal cancellation handling. + + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to install provider", + fmt.Sprintf("Error while installing %s v%s: %s", provider.ForDisplay(), version, err), + )) + } + }, + FetchPackageSuccess: func(provider addrs.Provider, version getproviders.Version, localDir string, authResult *getproviders.PackageAuthenticationResult) { + var keyID string + if authResult != nil && authResult.ThirdPartySigned() { + keyID = authResult.KeyID + } + if keyID != "" { + keyID = view.PrepareMessage(views.KeyID, keyID) + } + + view.LogInitMessage(views.InstalledProviderVersionInfo, provider.ForDisplay(), version, authResult, keyID) + }, + ProvidersLockUpdated: func(provider addrs.Provider, version getproviders.Version, localHashes []getproviders.Hash, signedHashes []getproviders.Hash, priorHashes []getproviders.Hash) { + // We're going to use this opportunity to track if we have any + // "incomplete" installs of providers. An incomplete install is + // when we are only going to write the local hashes into our lock + // file which means a `terraform init` command will fail in future + // when used on machines of a different architecture. + // + // We want to print a warning about this. + + if len(signedHashes) > 0 { + // If we have any signedHashes hashes then we don't worry - as + // we know we retrieved all available hashes for this version + // anyway. + return + } + + // If local hashes and prior hashes are exactly the same then + // it means we didn't record any signed hashes previously, and + // we know we're not adding any extra in now (because we already + // checked the signedHashes), so that's a problem. + // + // In the actual check here, if we have any priorHashes and those + // hashes are not the same as the local hashes then we're going to + // accept that this provider has been configured correctly. + if len(priorHashes) > 0 && !reflect.DeepEqual(localHashes, priorHashes) { + return + } + + // Now, either signedHashes is empty, or priorHashes is exactly the + // same as our localHashes which means we never retrieved the + // signedHashes previously. + // + // Either way, this is bad. Let's complain/warn. + c.incompleteProviders = append(c.incompleteProviders, provider.ForDisplay()) + }, + ProvidersFetched: func(authResults map[addrs.Provider]*getproviders.PackageAuthenticationResult) { + thirdPartySigned := false + for _, authResult := range authResults { + if authResult.ThirdPartySigned() { + thirdPartySigned = true + break + } + } + if thirdPartySigned { + view.LogInitMessage(views.PartnerAndCommunityProvidersMessage) + } + }, + } + + return events +} + // backendConfigOverrideBody interprets the raw values of -backend-config // arguments into a hcl Body that should override the backend settings given // in the configuration. diff --git a/internal/command/init_run.go b/internal/command/init_run.go index 5d3e6d172a65..50ddd5f5749d 100644 --- a/internal/command/init_run.go +++ b/internal/command/init_run.go @@ -8,11 +8,13 @@ import ( "fmt" "strings" + "github.com/hashicorp/hcl/v2" "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/cloud" "github.com/hashicorp/terraform/internal/command/arguments" "github.com/hashicorp/terraform/internal/command/views" "github.com/hashicorp/terraform/internal/configs" + "github.com/hashicorp/terraform/internal/depsfile" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/terraform" "github.com/hashicorp/terraform/internal/tfdiags" @@ -141,6 +143,22 @@ func (c *InitCommand) run(initArgs *arguments.Init, view views.Init) int { return 1 } + if !c.Meta.AllowExperimentalFeatures && rootModEarly.StateStore != nil { + // TODO(SarahFrench/radeksimko) - remove when this feature isn't experimental. + // This approach for making the feature experimental is required + // to let us assert the feature is gated behind an experiment in tests. + // See https://github.com/hashicorp/terraform/pull/37350#issuecomment-3168555619 + diags = diags.Append(earlyConfDiags) + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Unsupported block type", + Detail: "Blocks of type \"state_store\" are not expected here.", + Subject: &rootModEarly.StateStore.TypeRange, + }) + view.Diagnostics(diags) + + return 1 + } var back backend.Backend @@ -153,7 +171,8 @@ func (c *InitCommand) run(initArgs *arguments.Init, view views.Init) int { case initArgs.Cloud && rootModEarly.CloudConfig != nil: back, backendOutput, backDiags = c.initCloud(ctx, rootModEarly, initArgs.BackendConfig, initArgs.ViewType, view) case initArgs.Backend: - back, backendOutput, backDiags = c.initBackend(ctx, rootModEarly, initArgs.BackendConfig, initArgs.ViewType, view) + var locks *depsfile.Locks // Empty locks- this value is unused when a `backend` is used (vs. a `state_store`) + back, backendOutput, backDiags = c.initBackend(ctx, rootModEarly, initArgs, locks, view) default: // load the previously-stored backend config back, backDiags = c.Meta.backendFromState(ctx) diff --git a/internal/command/init_run_experiment.go b/internal/command/init_run_experiment.go new file mode 100644 index 000000000000..e4773d93b91f --- /dev/null +++ b/internal/command/init_run_experiment.go @@ -0,0 +1,347 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package command + +import ( + "errors" + "fmt" + "strings" + + "github.com/hashicorp/terraform/internal/backend" + "github.com/hashicorp/terraform/internal/cloud" + "github.com/hashicorp/terraform/internal/command/arguments" + "github.com/hashicorp/terraform/internal/command/views" + "github.com/hashicorp/terraform/internal/configs" + "github.com/hashicorp/terraform/internal/states" + "github.com/hashicorp/terraform/internal/terraform" + "github.com/hashicorp/terraform/internal/tfdiags" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" +) + +// `runPssInit` is an altered version of the logic in `run` that contains changes +// related to the PSS project. This is used by the (InitCommand.Run method only if Terraform has +// experimental features enabled. +func (c *InitCommand) runPssInit(initArgs *arguments.Init, view views.Init) int { + var diags tfdiags.Diagnostics + + c.forceInitCopy = initArgs.ForceInitCopy + c.Meta.stateLock = initArgs.StateLock + c.Meta.stateLockTimeout = initArgs.StateLockTimeout + c.reconfigure = initArgs.Reconfigure + c.migrateState = initArgs.MigrateState + c.Meta.ignoreRemoteVersion = initArgs.IgnoreRemoteVersion + c.Meta.input = initArgs.InputEnabled + c.Meta.targetFlags = initArgs.TargetFlags + c.Meta.compactWarnings = initArgs.CompactWarnings + + varArgs := initArgs.Vars.All() + items := make([]arguments.FlagNameValue, len(varArgs)) + for i := range varArgs { + items[i].Name = varArgs[i].Name + items[i].Value = varArgs[i].Value + } + c.Meta.variableArgs = arguments.FlagNameValueSlice{Items: &items} + + // Copying the state only happens during backend migration, so setting + // -force-copy implies -migrate-state + if c.forceInitCopy { + c.migrateState = true + } + + if len(initArgs.PluginPath) > 0 { + c.pluginPath = initArgs.PluginPath + } + + // Validate the arg count and get the working directory + path, err := ModulePath(initArgs.Args) + if err != nil { + diags = diags.Append(err) + view.Diagnostics(diags) + return 1 + } + + if err := c.storePluginPath(c.pluginPath); err != nil { + diags = diags.Append(fmt.Errorf("Error saving -plugin-dir to workspace directory: %s", err)) + view.Diagnostics(diags) + return 1 + } + + // Initialization can be aborted by interruption signals + ctx, done := c.InterruptibleContext(c.CommandContext()) + defer done() + + // This will track whether we outputted anything so that we know whether + // to output a newline before the success message + var header bool + + if initArgs.FromModule != "" { + src := initArgs.FromModule + + empty, err := configs.IsEmptyDir(path, initArgs.TestsDirectory) + if err != nil { + diags = diags.Append(fmt.Errorf("Error validating destination directory: %s", err)) + view.Diagnostics(diags) + return 1 + } + if !empty { + diags = diags.Append(errors.New(strings.TrimSpace(errInitCopyNotEmpty))) + view.Diagnostics(diags) + return 1 + } + + view.Output(views.CopyingConfigurationMessage, src) + header = true + + hooks := uiModuleInstallHooks{ + Ui: c.Ui, + ShowLocalPaths: false, // since they are in a weird location for init + View: view, + } + + ctx, span := tracer.Start(ctx, "-from-module=...", trace.WithAttributes( + attribute.String("module_source", src), + )) + + initDirFromModuleAbort, initDirFromModuleDiags := c.initDirFromModule(ctx, path, src, hooks) + diags = diags.Append(initDirFromModuleDiags) + if initDirFromModuleAbort || initDirFromModuleDiags.HasErrors() { + view.Diagnostics(diags) + span.SetStatus(codes.Error, "module installation failed") + span.End() + return 1 + } + span.End() + + view.Output(views.EmptyMessage) + } + + // If our directory is empty, then we're done. We can't get or set up + // the backend with an empty directory. + empty, err := configs.IsEmptyDir(path, initArgs.TestsDirectory) + if err != nil { + diags = diags.Append(fmt.Errorf("Error checking configuration: %s", err)) + view.Diagnostics(diags) + return 1 + } + if empty { + view.Output(views.OutputInitEmptyMessage) + return 0 + } + + // Load just the root module to begin backend and module initialization + rootModEarly, earlyConfDiags := c.loadSingleModuleWithTests(path, initArgs.TestsDirectory) + + // There may be parsing errors in config loading but these will be shown later _after_ + // checking for core version requirement errors. Not meeting the version requirement should + // be the first error displayed if that is an issue, but other operations are required + // before being able to check core version requirements. + if rootModEarly == nil { + diags = diags.Append(errors.New(view.PrepareMessage(views.InitConfigError)), earlyConfDiags) + view.Diagnostics(diags) + + return 1 + } + + if initArgs.Get { + modsOutput, modsAbort, modsDiags := c.getModules(ctx, path, initArgs.TestsDirectory, rootModEarly, initArgs.Upgrade, view) + diags = diags.Append(modsDiags) + if modsAbort || modsDiags.HasErrors() { + view.Diagnostics(diags) + return 1 + } + if modsOutput { + header = true + } + } + + // With all of the modules (hopefully) installed, we can now try to load the + // whole configuration tree. + config, confDiags := c.loadConfigWithTests(path, initArgs.TestsDirectory) + // configDiags will be handled after the version constraint check, since an + // incorrect version of terraform may be producing errors for configuration + // constructs added in later versions. + + // Before we go further, we'll check to make sure none of the modules in + // the configuration declare that they don't support this Terraform + // version, so we can produce a version-related error message rather than + // potentially-confusing downstream errors. + versionDiags := terraform.CheckCoreVersionRequirements(config) + if versionDiags.HasErrors() { + view.Diagnostics(versionDiags) + return 1 + } + + // Now the full configuration is loaded, we can download the providers specified in the configuration. + // This is step one of a two-step provider download process + // Providers may be downloaded by this code, but the dependency lock file is only updated later in `init` + // after step two of provider download is complete. + previousLocks, moreDiags := c.lockedDependencies() + diags = diags.Append(moreDiags) + + configProvidersOutput, configLocks, configProviderDiags := c.getProvidersFromConfig(ctx, config, initArgs.Upgrade, initArgs.PluginPath, initArgs.Lockfile, view) + diags = diags.Append(configProviderDiags) + if configProviderDiags.HasErrors() { + view.Diagnostics(diags) + return 1 + } + if configProvidersOutput { + header = true + } + + // If we outputted information, then we need to output a newline + // so that our success message is nicely spaced out from prior text. + if header { + view.Output(views.EmptyMessage) + } + + var back backend.Backend + + var backDiags tfdiags.Diagnostics + var backendOutput bool + switch { + case initArgs.Cloud && rootModEarly.CloudConfig != nil: + back, backendOutput, backDiags = c.initCloud(ctx, rootModEarly, initArgs.BackendConfig, initArgs.ViewType, view) + case initArgs.Backend: + // This handles case when config contains either backend or state_store blocks. + // This is valid as either can be implementations of backend.Backend, which is what we + // obtain here. + back, backendOutput, backDiags = c.initBackend(ctx, rootModEarly, initArgs, configLocks, view) + default: + // load the previously-stored backend config + back, backDiags = c.Meta.backendFromState(ctx) + } + if backendOutput { + header = true + } + if header { + // If we outputted information, then we need to output a newline + // so that our success message is nicely spaced out from prior text. + view.Output(views.EmptyMessage) + } + + var state *states.State + + // If we have a functional backend (either just initialized or initialized + // on a previous run) we'll use the current state as a potential source + // of provider dependencies. + if back != nil { + c.ignoreRemoteVersionConflict(back) + workspace, err := c.Workspace() + if err != nil { + diags = diags.Append(fmt.Errorf("Error selecting workspace: %s", err)) + view.Diagnostics(diags) + return 1 + } + sMgr, err := back.StateMgr(workspace) + if err != nil { + diags = diags.Append(fmt.Errorf("Error loading state: %s", err)) + view.Diagnostics(diags) + return 1 + } + + if err := sMgr.RefreshState(); err != nil { + diags = diags.Append(fmt.Errorf("Error refreshing state: %s", err)) + view.Diagnostics(diags) + return 1 + } + + state = sMgr.State() + } + + // Now the resource state is loaded, we can download the providers specified in the state but not the configuration. + // This is step two of a two-step provider download process + stateProvidersOutput, stateLocks, stateProvidersDiags := c.getProvidersFromState(ctx, state, configLocks, initArgs.Upgrade, initArgs.PluginPath, initArgs.Lockfile, view) + diags = diags.Append(configProviderDiags) + if stateProvidersDiags.HasErrors() { + view.Diagnostics(diags) + return 1 + } + if stateProvidersOutput { + header = true + } + if header { + // If we outputted information, then we need to output a newline + // so that our success message is nicely spaced out from prior text. + view.Output(views.EmptyMessage) + } + + // Now the two steps of provider download have happened, update the dependency lock file if it has changed. + lockFileOutput, lockFileDiags := c.saveDependencyLockFile(previousLocks, configLocks, stateLocks, initArgs.Lockfile, view) + diags = diags.Append(lockFileDiags) + if lockFileDiags.HasErrors() { + view.Diagnostics(diags) + return 1 + } + if lockFileOutput { + header = true + } + if header { + // If we outputted information, then we need to output a newline + // so that our success message is nicely spaced out from prior text. + view.Output(views.EmptyMessage) + } + + // As Terraform version-related diagnostics are handled above, we can now + // check the diagnostics from the early configuration and the backend. + diags = diags.Append(earlyConfDiags) + diags = diags.Append(backDiags) + if earlyConfDiags.HasErrors() { + diags = diags.Append(errors.New(view.PrepareMessage(views.InitConfigError))) + view.Diagnostics(diags) + return 1 + } + + // Now, we can show any errors from initializing the backend, but we won't + // show the InitConfigError preamble as we didn't detect problems with + // the early configuration. + if backDiags.HasErrors() { + view.Diagnostics(diags) + return 1 + } + + // If everything is ok with the core version check and backend initialization, + // show other errors from loading the full configuration tree. + diags = diags.Append(confDiags) + if confDiags.HasErrors() { + diags = diags.Append(errors.New(view.PrepareMessage(views.InitConfigError))) + view.Diagnostics(diags) + return 1 + } + + if cb, ok := back.(*cloud.Cloud); ok { + if c.RunningInAutomation { + if err := cb.AssertImportCompatible(config); err != nil { + diags = diags.Append(tfdiags.Sourceless(tfdiags.Error, "Compatibility error", err.Error())) + view.Diagnostics(diags) + return 1 + } + } + } + + // If we accumulated any warnings along the way that weren't accompanied + // by errors then we'll output them here so that the success message is + // still the final thing shown. + view.Diagnostics(diags) + _, cloud := back.(*cloud.Cloud) + output := views.OutputInitSuccessMessage + if cloud { + output = views.OutputInitSuccessCloudMessage + } + + view.Output(output) + + if !c.RunningInAutomation { + // If we're not running in an automation wrapper, give the user + // some more detailed next steps that are appropriate for interactive + // shell usage. + output = views.OutputInitSuccessCLIMessage + if cloud { + output = views.OutputInitSuccessCLICloudMessage + } + view.Output(output) + } + return 0 +} diff --git a/internal/command/init_test.go b/internal/command/init_test.go index d243344f52a8..d9ce8d9c748d 100644 --- a/internal/command/init_test.go +++ b/internal/command/init_test.go @@ -17,11 +17,15 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/cli" version "github.com/hashicorp/go-version" + tfaddr "github.com/hashicorp/terraform-registry-address" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/command/arguments" + "github.com/hashicorp/terraform/internal/command/clistate" "github.com/hashicorp/terraform/internal/command/views" + "github.com/hashicorp/terraform/internal/command/workdir" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/depsfile" @@ -111,6 +115,130 @@ func TestInit_only_test_files(t *testing.T) { } } +func TestInit_two_step_provider_download(t *testing.T) { + cases := map[string]struct { + workDirPath string + flags []string + expectedDownloadMsgs []string + }{ + "providers required by only the state file": { + // TODO - should the output indicate that no providers were found in config? + workDirPath: "init-provider-download/state-file-only", + expectedDownloadMsgs: []string{ + views.MessageRegistry[views.OutputInitSuccessCLIMessage].JSONValue, + `Initializing provider plugins found in the configuration... + Initializing the backend...`, // No providers found in the configuration so next output is backend-related + `Initializing provider plugins found in the state... + - Finding latest version of hashicorp/random... + - Installing hashicorp/random v9.9.9...`, // The latest version is expected, as state has no version constraints + }, + }, + "different providers required by config and state": { + workDirPath: "init-provider-download/config-and-state-different-providers", + expectedDownloadMsgs: []string{ + views.MessageRegistry[views.OutputInitSuccessCLIMessage].JSONValue, + + // Config - this provider is affected by a version constraint + `Initializing provider plugins found in the configuration... + - Finding hashicorp/null versions matching "< 9.0.0"... + - Installing hashicorp/null v1.0.0... + - Installed hashicorp/null v1.0.0`, + + // State - the latest version of this provider is expected, as state has no version constraints + `Initializing provider plugins found in the state... + - Finding latest version of hashicorp/random... + - Installing hashicorp/random v9.9.9...`, + }, + }, + "does not re-download providers that are present in both config and state": { + workDirPath: "init-provider-download/config-and-state-same-providers", + expectedDownloadMsgs: []string{ + // Config + `Initializing provider plugins found in the configuration... + - Finding hashicorp/random versions matching "< 9.0.0"... + - Installing hashicorp/random v1.0.0... + - Installed hashicorp/random v1.0.0`, + // State + `Initializing provider plugins found in the state... + - Reusing previous version of hashicorp/random + - Using previously-installed hashicorp/random v1.0.0`, + }, + }, + "reuses providers already represented in a dependency lock file": { + workDirPath: "init-provider-download/config-state-file-and-lockfile", + expectedDownloadMsgs: []string{ + // Config + `Initializing provider plugins found in the configuration... + - Reusing previous version of hashicorp/random from the dependency lock file + - Installing hashicorp/random v1.0.0... + - Installed hashicorp/random v1.0.0`, + // State + `Initializing provider plugins found in the state... + - Reusing previous version of hashicorp/random + - Using previously-installed hashicorp/random v1.0.0`, + }, + }, + "using the -upgrade flag causes provider download to ignore the lock file": { + workDirPath: "init-provider-download/config-state-file-and-lockfile", + flags: []string{"-upgrade"}, + expectedDownloadMsgs: []string{ + // Config - lock file is not mentioned due to the -upgrade flag + `Initializing provider plugins found in the configuration... + - Finding hashicorp/random versions matching "< 9.0.0"... + - Installing hashicorp/random v1.0.0... + - Installed hashicorp/random v1.0.0`, + // State - reuses the provider download from the config + `Initializing provider plugins found in the state... + - Reusing previous version of hashicorp/random + - Using previously-installed hashicorp/random v1.0.0`, + }, + }, + } + + for tn, tc := range cases { + t.Run(tn, func(t *testing.T) { + + // Create a temporary working directory no tf configuration but has state + td := t.TempDir() + testCopyDir(t, testFixturePath(tc.workDirPath), td) + os.MkdirAll(td, 0755) + t.Chdir(td) + + // A provider source containing the random and null providers + providerSource, close := newMockProviderSource(t, map[string][]string{ + "hashicorp/random": {"1.0.0", "9.9.9"}, + "hashicorp/null": {"1.0.0", "9.9.9"}, + }) + defer close() + + ui := new(cli.MockUi) + view, done := testView(t) + c := &InitCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + View: view, + ProviderSource: providerSource, + + AllowExperimentalFeatures: true, // Needed to test init changes for PSS project + }, + } + + args := append(tc.flags, "-enable-pluggable-state-storage-experiment") // Needed to test init changes for PSS project + if code := c.Run(args); code != 0 { + t.Fatalf("bad: \n%s", done(t).All()) + } + + actual := cleanString(done(t).All()) + for _, downloadMsg := range tc.expectedDownloadMsgs { + if !strings.Contains(cleanString(actual), cleanString(downloadMsg)) { + t.Fatalf("expected output to contain %q\n, got %q", cleanString(downloadMsg), cleanString(actual)) + } + } + }) + } +} + func TestInit_multipleArgs(t *testing.T) { // Create a temporary working directory that is empty td := t.TempDir() @@ -3133,6 +3261,242 @@ func TestInit_stateStoreBlockIsExperimental(t *testing.T) { } } +// Testing init's behaviors when run in an empty working directory. +func TestInit_stateStore_newWorkingDir(t *testing.T) { + t.Run("the init command creates a backend state file, and creates the default workspace by default", func(t *testing.T) { + // Create a temporary, uninitialized working directory with configuration including a state store + td := t.TempDir() + testCopyDir(t, testFixturePath("init-with-state-store"), td) + t.Chdir(td) + + mockProvider := mockPluggableStateStorageProvider() + mockProviderAddress := addrs.NewDefaultProvider("test") + providerSource, close := newMockProviderSource(t, map[string][]string{ + "hashicorp/test": {"1.0.0"}, + }) + defer close() + + ui := new(cli.MockUi) + view, done := testView(t) + meta := Meta{ + Ui: ui, + View: view, + AllowExperimentalFeatures: true, + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + mockProviderAddress: providers.FactoryFixed(mockProvider), + }, + }, + ProviderSource: providerSource, + } + c := &InitCommand{ + Meta: meta, + } + + args := []string{"-enable-pluggable-state-storage-experiment=true"} + code := c.Run(args) + testOutput := done(t) + if code != 0 { + t.Fatalf("expected code 0 exit code, got %d, output: \n%s", code, testOutput.All()) + } + + // Check output + output := testOutput.All() + expectedOutputs := []string{ + "Initializing the state store...", + "Terraform has been successfully initialized!", + } + for _, expected := range expectedOutputs { + if !strings.Contains(output, expected) { + t.Fatalf("expected output to include %q, but got':\n %s", expected, output) + } + } + + // Assert the default workspace was created + if _, exists := mockProvider.MockStates[backend.DefaultStateName]; !exists { + t.Fatal("expected the default workspace to be created during init, but it is missing") + } + + // Assert contents of the backend state file + statePath := filepath.Join(meta.DataDir(), DefaultStateFilename) + sMgr := &clistate.LocalState{Path: statePath} + if err := sMgr.RefreshState(); err != nil { + t.Fatal("Failed to load state:", err) + } + s := sMgr.State() + if s == nil { + t.Fatal("expected backend state file to be created, but there isn't one") + } + v1_0_0, _ := version.NewVersion("1.0.0") + expectedState := &workdir.StateStoreConfigState{ + Type: "test_store", + ConfigRaw: []byte("{\n \"value\": null\n }"), + Hash: uint64(3976463117), // Hash of empty config + Provider: &workdir.ProviderConfigState{ + Version: v1_0_0, + Source: &tfaddr.Provider{ + Hostname: tfaddr.DefaultProviderRegistryHost, + Namespace: "hashicorp", + Type: "test", + }, + ConfigRaw: []byte("{\n \"region\": null\n }"), + Hash: uint64(3976463117), // Hash of empty config + }, + } + if diff := cmp.Diff(s.StateStore, expectedState); diff != "" { + t.Fatalf("unexpected diff in backend state file's description of state store:\n%s", diff) + } + }) + + t.Run("an init command with the flag -create-default-workspace=false will not make the default workspace", func(t *testing.T) { + // Create a temporary, uninitialized working directory with configuration including a state store + td := t.TempDir() + testCopyDir(t, testFixturePath("init-with-state-store"), td) + t.Chdir(td) + + mockProvider := mockPluggableStateStorageProvider() + mockProviderAddress := addrs.NewDefaultProvider("test") + providerSource, close := newMockProviderSource(t, map[string][]string{ + "hashicorp/test": {"1.0.0"}, + }) + defer close() + + ui := new(cli.MockUi) + view, done := testView(t) + c := &InitCommand{ + Meta: Meta{ + Ui: ui, + View: view, + AllowExperimentalFeatures: true, + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + mockProviderAddress: providers.FactoryFixed(mockProvider), + }, + }, + ProviderSource: providerSource, + }, + } + + args := []string{"-enable-pluggable-state-storage-experiment=true", "-create-default-workspace=false"} + code := c.Run(args) + testOutput := done(t) + if code != 0 { + t.Fatalf("expected code 0 exit code, got %d, output: \n%s", code, testOutput.All()) + } + + // Check output + output := testOutput.All() + expectedOutput := `Terraform has been configured to skip creation of the default workspace` + if !strings.Contains(output, expectedOutput) { + t.Fatalf("expected output to include %q, but got':\n %s", expectedOutput, output) + } + + // Assert the default workspace was created + if _, exists := mockProvider.MockStates[backend.DefaultStateName]; exists { + t.Fatal("expected Terraform to skip creating the default workspace, but it has been created") + } + }) + + // TODO: Add test cases below once PSS feature isn't experimental. + // Currently these tests are handled at a lower level in `internal/command/meta_backend_test.go`: + // > "during a non-init command, the command ends in with an error telling the user to run an init command" +} + +// Testing init's behaviors when run in a working directory where the configuration +// doesn't match the backend state file. +func TestInit_stateStore_configChanges(t *testing.T) { + t.Run("the -reconfigure flag makes Terraform ignore the backend state file during initialization", func(t *testing.T) { + // Create a temporary working directory with state store configuration + // that doesn't match the backend state file + td := t.TempDir() + testCopyDir(t, testFixturePath("state-store-reconfigure"), td) + t.Chdir(td) + + mockProvider := mockPluggableStateStorageProvider() + mockProviderAddress := addrs.NewDefaultProvider("test") + providerSource, close := newMockProviderSource(t, map[string][]string{ + "hashicorp/test": {"1.0.0"}, + }) + defer close() + + ui := new(cli.MockUi) + view, done := testView(t) + meta := Meta{ + Ui: ui, + View: view, + AllowExperimentalFeatures: true, + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + mockProviderAddress: providers.FactoryFixed(mockProvider), + }, + }, + ProviderSource: providerSource, + } + c := &InitCommand{ + Meta: meta, + } + + args := []string{ + "-enable-pluggable-state-storage-experiment=true", + "-reconfigure", + } + code := c.Run(args) + testOutput := done(t) + if code != 0 { + t.Fatalf("expected code 0 exit code, got %d, output: \n%s", code, testOutput.All()) + } + + // Check output + output := testOutput.All() + expectedOutputs := []string{ + "Initializing the state store...", + "Terraform has been successfully initialized!", + } + for _, expected := range expectedOutputs { + if !strings.Contains(output, expected) { + t.Fatalf("expected output to include %q, but got':\n %s", expected, output) + } + } + + // Assert the default workspace was created + if _, exists := mockProvider.MockStates[backend.DefaultStateName]; !exists { + t.Fatal("expected the default workspace to be created during init, but it is missing") + } + + // Assert contents of the backend state file + statePath := filepath.Join(meta.DataDir(), DefaultStateFilename) + sMgr := &clistate.LocalState{Path: statePath} + if err := sMgr.RefreshState(); err != nil { + t.Fatal("Failed to load state:", err) + } + s := sMgr.State() + if s == nil { + t.Fatal("expected backend state file to be created, but there isn't one") + } + v1_0_0, _ := version.NewVersion("1.0.0") + expectedState := &workdir.StateStoreConfigState{ + Type: "test_store", + ConfigRaw: []byte("{\n \"value\": \"changed-value\"\n }"), + Hash: uint64(1417640992), // Hash affected by config + Provider: &workdir.ProviderConfigState{ + Version: v1_0_0, + Source: &tfaddr.Provider{ + Hostname: tfaddr.DefaultProviderRegistryHost, + Namespace: "hashicorp", + Type: "test", + }, + ConfigRaw: []byte("{\n \"region\": null\n }"), + Hash: uint64(3976463117), // Hash of empty config + }, + } + if diff := cmp.Diff(s.StateStore, expectedState); diff != "" { + t.Fatalf("unexpected diff in backend state file's description of state store:\n%s", diff) + } + }) + + // TODO - add more test cases, e.g. these context changes in the context of updating providers +} + // newMockProviderSource is a helper to succinctly construct a mock provider // source that contains a set of packages matching the given provider versions // that are available for installation (from temporary local files). @@ -3273,3 +3637,65 @@ func expectedPackageInstallPath(name, version string, exe bool) string { baseDir, fmt.Sprintf("registry.terraform.io/hashicorp/%s/%s/%s", name, version, platform), )) } + +func mockPluggableStateStorageProvider() *testing_provider.MockProvider { + // Create a mock provider to use for PSS + // Get mock provider factory to be used during init + // + // This imagines a provider called `test` that contains + // a pluggable state store implementation called `store`. + pssName := "test_store" + mock := testing_provider.MockProvider{ + GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{ + Provider: providers.Schema{ + Body: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "region": {Type: cty.String, Optional: true}, + }, + }, + }, + DataSources: map[string]providers.Schema{}, + ResourceTypes: map[string]providers.Schema{}, + ListResourceTypes: map[string]providers.Schema{}, + StateStores: map[string]providers.Schema{ + pssName: { + Body: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "value": { + Type: cty.String, + Required: true, + }, + }, + }, + }, + }, + }, + } + mock.WriteStateBytesFn = func(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + // Workspaces exist once the artefact representing it is written + if _, exist := mock.MockStates[req.StateId]; !exist { + // Ensure non-nil map + if mock.MockStates == nil { + mock.MockStates = make(map[string]interface{}) + } + + mock.MockStates[req.StateId] = req.Bytes + } + return providers.WriteStateBytesResponse{ + Diagnostics: nil, // success + } + } + mock.ReadStateBytesFn = func(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + state := []byte{} + if v, exist := mock.MockStates[req.StateId]; exist { + if s, ok := v.([]byte); ok { + state = s + } + } + return providers.ReadStateBytesResponse{ + Bytes: state, + Diagnostics: nil, // success + } + } + return &mock +} diff --git a/internal/command/meta_backend.go b/internal/command/meta_backend.go index 8b3559e7471a..baa7bbc4f896 100644 --- a/internal/command/meta_backend.go +++ b/internal/command/meta_backend.go @@ -14,31 +14,39 @@ import ( "fmt" "log" "maps" + "os" "path/filepath" "slices" "strconv" "strings" + version "github.com/hashicorp/go-version" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hcldec" "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/backend/backendrun" backendInit "github.com/hashicorp/terraform/internal/backend/init" backendLocal "github.com/hashicorp/terraform/internal/backend/local" + backendPluggable "github.com/hashicorp/terraform/internal/backend/pluggable" "github.com/hashicorp/terraform/internal/cloud" "github.com/hashicorp/terraform/internal/command/arguments" "github.com/hashicorp/terraform/internal/command/clistate" "github.com/hashicorp/terraform/internal/command/views" "github.com/hashicorp/terraform/internal/command/workdir" "github.com/hashicorp/terraform/internal/configs" + "github.com/hashicorp/terraform/internal/depsfile" "github.com/hashicorp/terraform/internal/didyoumean" + "github.com/hashicorp/terraform/internal/getproviders/providerreqs" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" + "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/states/statemgr" "github.com/hashicorp/terraform/internal/terraform" "github.com/hashicorp/terraform/internal/tfdiags" + tfversion "github.com/hashicorp/terraform/version" ) // BackendOpts are the options used to initialize a backendrun.OperationsBackend. @@ -58,6 +66,13 @@ type BackendOpts struct { // This will only be set if the configuration contains a state_store block. ProviderFactory providers.Factory + // Locks allows state-migration logic to detect when the provider used for pluggable state storage + // during the last init (i.e. what's in the backend state file) is mismatched with the provider + // version in use currently. + // + // This will only be set if the configuration contains a state_store block. + Locks *depsfile.Locks + // ConfigOverride is an hcl.Body that, if non-nil, will be used with // configs.MergeBodies to override the type-specific backend configuration // arguments in Config. @@ -75,6 +90,10 @@ type BackendOpts struct { // ViewType will set console output format for the // initialization operation (JSON or human-readable). ViewType arguments.ViewType + + // CreateDefaultWorkspace signifies whether the operations backend should create + // the default workspace or not + CreateDefaultWorkspace bool } // BackendWithRemoteTerraformVersion is a shared interface between the 'remote' and 'cloud' backends @@ -222,7 +241,7 @@ func (m *Meta) Backend(opts *BackendOpts) (backendrun.OperationsBackend, tfdiags } } - return local, nil + return local, diags } // selectWorkspace gets a list of existing workspaces and then checks @@ -628,11 +647,13 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di // Get the local 'backend' or 'state_store' configuration. var backendConfig *configs.Backend var stateStoreConfig *configs.StateStore - var cHash int + var cHash int // backend hash + var stateStoreHash int + var stateStoreProviderHash int if opts.StateStoreConfig != nil { // state store has been parsed from config and is included in opts var ssDiags tfdiags.Diagnostics - stateStoreConfig, cHash, _, ssDiags = m.stateStoreConfig(opts) + stateStoreConfig, stateStoreHash, stateStoreProviderHash, ssDiags = m.stateStoreConfig(opts) diags = diags.Append(ssDiags) if ssDiags.HasErrors() { return nil, diags @@ -671,7 +692,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di statePath := filepath.Join(m.DataDir(), DefaultStateFilename) sMgr := &clistate.LocalState{Path: statePath} if err := sMgr.RefreshState(); err != nil { - diags = diags.Append(fmt.Errorf("Failed to load state: %s", err)) + diags = diags.Append(fmt.Errorf("Failed to load the backend state file: %s", err)) return nil, diags } @@ -784,11 +805,22 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di stateStoreConfig.Provider.Name, stateStoreConfig.ProviderAddr, ) - return nil, diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Not implemented yet", - Detail: "Configuring a state store for the first time is not implemented yet", - }) + + if !opts.Init { + initReason := fmt.Sprintf("Initial configuration of the requested state_store %q in provider %s (%q)", + stateStoreConfig.Type, + stateStoreConfig.Provider.Name, + stateStoreConfig.ProviderAddr, + ) + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "State store initialization required, please run \"terraform init\"", + fmt.Sprintf(strings.TrimSpace(errStateStoreInit), initReason), + )) + return nil, diags + } + + return m.stateStore_C_s(stateStoreConfig, stateStoreHash, stateStoreProviderHash, sMgr, opts) // Migration from state store to backend case backendConfig != nil && s.Backend.Empty() && @@ -1072,7 +1104,7 @@ func (m *Meta) backendFromState(_ context.Context) (backend.Backend, tfdiags.Dia // Unconfiguring a backend (moving from backend => local). func (m *Meta) backend_c_r_S( - c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { + c *configs.Backend, cHash int, backendSMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics @@ -1083,7 +1115,8 @@ func (m *Meta) backend_c_r_S( vt = arguments.ViewHuman } - s := sMgr.State() + // Get backend state file data + s := backendSMgr.State() cloudMode := cloud.DetectConfigChangeType(s.Backend, c, false) diags = diags.Append(m.assertSupportedCloudInitOptions(cloudMode)) @@ -1108,7 +1141,7 @@ func (m *Meta) backend_c_r_S( } // Initialize the configured backend - b, moreDiags := m.savedBackend(sMgr) + b, moreDiags := m.savedBackend(backendSMgr) diags = diags.Append(moreDiags) if moreDiags.HasErrors() { return nil, diags @@ -1129,11 +1162,11 @@ func (m *Meta) backend_c_r_S( // Remove the stored metadata s.Backend = nil - if err := sMgr.WriteState(s); err != nil { + if err := backendSMgr.WriteState(s); err != nil { diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendClearSaved), err)) return nil, diags } - if err := sMgr.PersistState(); err != nil { + if err := backendSMgr.PersistState(); err != nil { diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendClearSaved), err)) return nil, diags } @@ -1149,7 +1182,7 @@ func (m *Meta) backend_c_r_S( } // Configuring a backend for the first time. -func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.LocalState, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { +func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, backendSMgr *clistate.LocalState, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics vt := arguments.ViewJSON @@ -1253,15 +1286,15 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local if m.stateLock { view := views.NewStateLocker(vt, m.View) stateLocker := clistate.NewLocker(m.stateLockTimeout, view) - if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil { + if err := stateLocker.Lock(backendSMgr, "backend from plan"); err != nil { diags = diags.Append(fmt.Errorf("Error locking state: %s", err)) return nil, diags } defer stateLocker.Unlock() } - // Store the metadata in our saved state location - s := sMgr.State() + // Store the backend's metadata in our the backend state file location + s := backendSMgr.State() if s == nil { s = workdir.NewBackendStateFile() } @@ -1296,11 +1329,12 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local } } - if err := sMgr.WriteState(s); err != nil { + // Update backend state file + if err := backendSMgr.WriteState(s); err != nil { diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) return nil, diags } - if err := sMgr.PersistState(); err != nil { + if err := backendSMgr.PersistState(); err != nil { diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) return nil, diags } @@ -1316,7 +1350,7 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local } // Changing a previously saved backend. -func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { +func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, backendSMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics vt := arguments.ViewJSON @@ -1326,8 +1360,8 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista vt = arguments.ViewHuman } - // Get the old state - s := sMgr.State() + // Get the old backend state file data + s := backendSMgr.State() cloudMode := cloud.DetectConfigChangeType(s.Backend, c, false) diags = diags.Append(m.assertSupportedCloudInitOptions(cloudMode)) @@ -1373,7 +1407,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista // state lives. if cloudMode != cloud.ConfigChangeInPlace { // Grab the existing backend - oldB, oldBDiags := m.savedBackend(sMgr) + oldB, oldBDiags := m.savedBackend(backendSMgr) diags = diags.Append(oldBDiags) if oldBDiags.HasErrors() { return nil, diags @@ -1395,7 +1429,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista if m.stateLock { view := views.NewStateLocker(vt, m.View) stateLocker := clistate.NewLocker(m.stateLockTimeout, view) - if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil { + if err := stateLocker.Lock(backendSMgr, "backend from plan"); err != nil { diags = diags.Append(fmt.Errorf("Error locking state: %s", err)) return nil, diags } @@ -1404,7 +1438,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista } // Update the backend state - s = sMgr.State() + s = backendSMgr.State() if s == nil { s = workdir.NewBackendStateFile() } @@ -1426,11 +1460,12 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista } } - if err := sMgr.WriteState(s); err != nil { + // Save data to backend state file + if err := backendSMgr.WriteState(s); err != nil { diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) return nil, diags } - if err := sMgr.PersistState(); err != nil { + if err := backendSMgr.PersistState(); err != nil { diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) return nil, diags } @@ -1447,15 +1482,322 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista return b, diags } +//------------------------------------------------------------------- +// State Store Config Scenarios +// The functions below cover handling all the various scenarios that +// can exist when loading a state store. They are named in the format of +// "stateStore_C_S" where C and S may be upper or lowercase. Lowercase +// means it is false, uppercase means it is true. +// +// The fields are: +// +// * C - State store configuration is set and changed in TF files +// * S - State store configuration is set in the state +// +//------------------------------------------------------------------- + +// Configuring a state_store for the first time. +func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, providerHash int, backendSMgr *clistate.LocalState, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + vt := arguments.ViewJSON + // Set default viewtype if none was set as the StateLocker needs to know exactly + // what viewType we want to have. + if opts == nil || opts.ViewType != vt { + vt = arguments.ViewHuman + } + + // Grab a purely local backend to get the local state if it exists + localB, localBDiags := m.Backend(&BackendOpts{ForceLocal: true, Init: true}) + if localBDiags.HasErrors() { + diags = diags.Append(localBDiags) + return nil, diags + } + + workspaces, err := localB.Workspaces() + if err != nil { + diags = diags.Append(fmt.Errorf(errBackendLocalRead, err)) + return nil, diags + } + + var localStates []statemgr.Full + for _, workspace := range workspaces { + localState, err := localB.StateMgr(workspace) + if err != nil { + diags = diags.Append(fmt.Errorf(errBackendLocalRead, err)) + return nil, diags + } + if err := localState.RefreshState(); err != nil { + diags = diags.Append(fmt.Errorf(errBackendLocalRead, err)) + return nil, diags + } + + // We only care about non-empty states. + if localS := localState.State(); !localS.Empty() { + log.Printf("[TRACE] Meta.Backend: will need to migrate workspace states because of existing %q workspace", workspace) + localStates = append(localStates, localState) + } else { + log.Printf("[TRACE] Meta.Backend: ignoring local %q workspace because its state is empty", workspace) + } + } + + // Get the state store as an instance of backend.Backend + b, storeConfigVal, providerConfigVal, moreDiags := m.stateStoreInitFromConfig(c, opts) + diags = diags.Append(moreDiags) + if diags.HasErrors() { + return nil, diags + } + + if len(localStates) > 0 { + // Migrate any local states into the new state store + err = m.backendMigrateState(&backendMigrateOpts{ + SourceType: "local", + DestinationType: c.Type, + Source: localB, + Destination: b, + ViewType: vt, + }) + if err != nil { + diags = diags.Append(err) + return nil, diags + } + + // We remove the local state after migration to prevent confusion + // As we're migrating to a state store we don't have insight into whether it stores + // files locally at all, and whether those local files conflict with the location of + // the old local state. + log.Printf("[TRACE] Meta.Backend: removing old state snapshots from old backend") + for _, localState := range localStates { + // We always delete the local state, unless that was our new state too. + if err := localState.WriteState(nil); err != nil { + diags = diags.Append(fmt.Errorf(errBackendMigrateLocalDelete, err)) + return nil, diags + } + if err := localState.PersistState(nil); err != nil { + diags = diags.Append(fmt.Errorf(errBackendMigrateLocalDelete, err)) + return nil, diags + } + } + } + + if m.stateLock { + view := views.NewStateLocker(vt, m.View) + stateLocker := clistate.NewLocker(m.stateLockTimeout, view) + if err := stateLocker.Lock(backendSMgr, "init is initializing state_store first time"); err != nil { + diags = diags.Append(fmt.Errorf("Error locking state: %s", err)) + return nil, diags + } + defer stateLocker.Unlock() + } + + // Store the state_store metadata in our saved state location + s := backendSMgr.State() + if s == nil { + s = workdir.NewBackendStateFile() + } + + var pVersion *version.Version + if c.ProviderAddr.Equals(addrs.NewBuiltInProvider("terraform")) { + // If we're handling the builtin "terraform" provider then there's no version information to store in the dependency lock file, so don't access it. + // We must record a value into the backend state file, and we cannot include a value that changes (e.g. the Terraform core binary version) as migration + // is impossible with builtin providers. + // So, we use an arbitrary stand-in version. + standInVersion, err := version.NewVersion("0.0.1") + if err != nil { + diags = diags.Append(fmt.Errorf("Error when creating a backend state file. This is a bug in Terraform and should be reported: %w", + err)) + return nil, diags + } + pVersion = standInVersion + } else { + isReattached, err := isProviderReattached(c.ProviderAddr) + if err != nil { + diags = diags.Append(fmt.Errorf("Error determining if the state storage provider is reattached or not. This is a bug in Terraform and should be reported: %w", + err)) + return nil, diags + } + if isReattached { + // If the provider is unmanaged then it won't be in the locks. + // If there are no locks then there's no version information to for us to access and use when creating the backend state file. + // So, we use an arbitrary stand-in version. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "State storage provider is not managed by Terraform", + Detail: "Terraform is using a provider supplied via TF_REATTACH_PROVIDERS for initializing state storage. This will affect Terraform's ability to detect when state migrations are required.", + }) + standInVersion, err := version.NewVersion("0.0.1") + if err != nil { + diags = diags.Append(fmt.Errorf("Error when creating a backend state file. This is a bug in Terraform and should be reported: %w", + err)) + return nil, diags + } + pVersion = standInVersion + } else { + // The provider is not built in and is being managed by Terraform + // This is the most common scenario, by far. + pLock := opts.Locks.Provider(c.ProviderAddr) + if pLock == nil { + diags = diags.Append(fmt.Errorf("The provider %s (%q) is not present in the lockfile, despite being used for state store %q. This is a bug in Terraform and should be reported.", + c.Provider.Name, + c.ProviderAddr, + c.Type)) + return nil, diags + } + pVersion, err = providerreqs.GoVersionFromVersion(pLock.Version()) + if err != nil { + diags = diags.Append(fmt.Errorf("Failed obtain the in-use version of provider %s (%q) when recording backend state for state store %q. This is a bug in Terraform and should be reported: %w", + c.Provider.Name, + c.ProviderAddr, + c.Type, + err)) + return nil, diags + } + } + } + s.StateStore = &workdir.StateStoreConfigState{ + Type: c.Type, + Hash: uint64(stateStoreHash), + Provider: &workdir.ProviderConfigState{ + Source: &c.ProviderAddr, + Version: pVersion, + Hash: uint64(providerHash), + }, + } + s.StateStore.SetConfig(storeConfigVal, b.ConfigSchema()) + if plug, ok := b.(*backendPluggable.Pluggable); ok { + // We need to convert away from backend.Backend interface to use the method + // for accessing the provider schema. + s.StateStore.Provider.SetConfig(providerConfigVal, plug.ProviderSchema()) + } + + // Verify that selected workspace exists in the state store. + if opts.Init && b != nil { + err := m.selectWorkspace(b) + if err != nil { + if strings.Contains(err.Error(), "No existing workspaces") { + // If there are no workspaces, Terraform either needs to create the default workspace here, + // or instruct the user to run a `terraform workspace new` command. + ws, err := m.Workspace() + if err != nil { + diags = diags.Append(fmt.Errorf("Failed to check current workspace: %w", err)) + return nil, diags + } + + switch { + case ws != backend.DefaultStateName: + // User needs to run a `terraform workspace new` command. + diags = append(diags, tfdiags.Sourceless( + tfdiags.Error, + fmt.Sprintf("Workspace %q has not been created yet", ws), + fmt.Sprintf("State store %q in provider %s (%q) reports that no workspaces currently exist. To create the custom workspace %q use the command `terraform workspace new %s`.", + c.Type, + c.Provider.Name, + c.ProviderAddr, + ws, + ws, + ), + )) + return nil, diags + + case ws == backend.DefaultStateName: + // Users control if the default workspace is created through the -create-default-workspace flag (defaults to true) + if opts.CreateDefaultWorkspace { + diags = diags.Append(m.createDefaultWorkspace(c, b)) + } else { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "The default workspace does not exist", + Detail: "Terraform has been configured to skip creation of the default workspace in the state store. To create it, either run an 'init' command without `-create-default-workspace=true`, or create it using a 'workspace new' command", + }) + } + default: + diags = diags.Append(err) + return nil, diags + } + } else { + // For all other errors, report via diagnostics + diags = diags.Append(fmt.Errorf("Failed to select a workspace: %w", err)) + } + } + } + if diags.HasErrors() { + return nil, diags + } + + // Update backend state file + if err := backendSMgr.WriteState(s); err != nil { + diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) + return nil, diags + } + if err := backendSMgr.PersistState(); err != nil { + diags = diags.Append(fmt.Errorf(errBackendWriteSaved, err)) + return nil, diags + } + + return b, diags +} + +// isProviderReattached determines if a given provider is being supplied to Terraform via the TF_REATTACH_PROVIDERS +// environment variable. +func isProviderReattached(provider addrs.Provider) (bool, error) { + in := os.Getenv("TF_REATTACH_PROVIDERS") + if in != "" { + var m map[string]any + err := json.Unmarshal([]byte(in), &m) + if err != nil { + return false, fmt.Errorf("Invalid format for TF_REATTACH_PROVIDERS: %w", err) + } + for p, _ := range m { + a, diags := addrs.ParseProviderSourceString(p) + if diags.HasErrors() { + return false, fmt.Errorf("Error parsing %q as a provider address: %w", a, diags.Err()) + } + if a.Equals(provider) { + return true, nil + } + } + } + return false, nil +} + +// createDefaultWorkspace receives a backend made using a pluggable state store, and details about that store's config, +// and persists an empty state file in the default workspace. By creating this artifact we ensure that the default +// workspace is created and usable by Terraform in later operations. +func (m *Meta) createDefaultWorkspace(c *configs.StateStore, b backend.Backend) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + + defaultSMgr, err := b.StateMgr(backend.DefaultStateName) + if err != nil { + diags = diags.Append(fmt.Errorf("Failed to create a state manager for state store %q in provider %s (%q). This is a bug in Terraform and should be reported: %w", + c.Type, + c.Provider.Name, + c.ProviderAddr, + err)) + return diags + } + emptyState := states.NewState() + if err := defaultSMgr.WriteState(emptyState); err != nil { + diags = diags.Append(fmt.Errorf(errStateStoreWorkspaceCreate, c.Type, err)) + return diags + } + // TODO - implement Read/Write state RPC methods + if err := defaultSMgr.PersistState(nil); err != nil { + diags = diags.Append(fmt.Errorf(errStateStoreWorkspaceCreate, c.Type, err)) + return diags + } + + return diags +} + // Initializing a saved backend from the cache file (legacy state file) // // TODO: This is extremely similar to Meta.backendFromState() but for legacy reasons this is the // function used by the migration APIs within this file. The other handles 'init -backend=false', // specifically. -func (m *Meta) savedBackend(sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { +func (m *Meta) savedBackend(backendSMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics - s := sMgr.State() + s := backendSMgr.State() // Get the backend f := backendInit.Backend(s.Backend.Type) @@ -1644,6 +1986,181 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V return b, configVal, diags } +// stateStoreInitFromConfig returns an initialized and configured state store, using the backend.Backend interface. +// During this process: +// > Users are prompted for input if required attributes are missing. +// > The provider is configured, after validating provider config +// > The state store is configured, after validating state_store config +func (m *Meta) stateStoreInitFromConfig(c *configs.StateStore, opts *BackendOpts) (backend.Backend, cty.Value, cty.Value, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + provider, err := opts.ProviderFactory() + if err != nil { + diags = diags.Append(fmt.Errorf("error when obtaining provider instance during state store initialization: %w", err)) + return nil, cty.NilVal, cty.NilVal, diags + } + // We purposefully don't have a deferred call to the provider's Close method here because the calling code needs a + // running provider instance inside the returned backend.Backend instance. + // Stopping the provider process is the responsibility of the calling code. + + resp := provider.GetProviderSchema() + + if len(resp.StateStores) == 0 { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Provider does not support pluggable state storage", + Detail: fmt.Sprintf("There are no state stores implemented by provider %s (%q)", + c.Provider.Name, + c.ProviderAddr), + Subject: &c.DeclRange, + }) + return nil, cty.NilVal, cty.NilVal, diags + } + + schema, exists := resp.StateStores[c.Type] + if !exists { + suggestions := slices.Sorted(maps.Keys(resp.StateStores)) + suggestion := didyoumean.NameSuggestion(c.Type, suggestions) + if suggestion != "" { + suggestion = fmt.Sprintf(" Did you mean %q?", suggestion) + } + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "State store not implemented by the provider", + Detail: fmt.Sprintf("State store %q is not implemented by provider %s (%q)%s", + c.Type, c.Provider.Name, + c.ProviderAddr, suggestion), + Subject: &c.DeclRange, + }) + return nil, cty.NilVal, cty.NilVal, diags + } + + // Handle the nested provider block. + pDecSpec := resp.Provider.Body.NoneRequired().DecoderSpec() + pConfig := c.Provider.Config + providerConfigVal, pDecDiags := hcldec.Decode(pConfig, pDecSpec, nil) + diags = diags.Append(pDecDiags) + + if !providerConfigVal.IsWhollyKnown() { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Unknown values within state_store's nested provider block", + "The `terraform` configuration block should contain only concrete and static values. Another diagnostic should contain more information about which part of the configuration is problematic.")) + return nil, cty.NilVal, cty.NilVal, diags + } + + if m.Input() { + var err error + // TODO (SarahFrench/radeksimko) - Should we allow input to the provider block? + providerConfigVal, err = m.inputForSchema(providerConfigVal, resp.Provider.Body) + if err != nil { + diags = diags.Append( + fmt.Errorf("Error asking for input to configure provider %s (%q) for state store %q: %s", + c.Provider.Name, + c.ProviderAddr, + c.Type, + err, + ), + ) + return nil, cty.NilVal, cty.NilVal, diags + } + + // We get an unknown here if the if the user aborted input, but we can't + // turn that into a config value, so set it to null and let the provider + // handle it in PrepareConfig. + if !providerConfigVal.IsKnown() { + providerConfigVal = cty.NullVal(providerConfigVal.Type()) + } + } + + // Handle the schema for the state store itself, excluding the provider block. + ssdecSpec := schema.Body.NoneRequired().DecoderSpec() + stateStoreConfigVal, ssDecDiags := hcldec.Decode(c.Config, ssdecSpec, nil) + diags = diags.Append(ssDecDiags) + if ssDecDiags.HasErrors() { + return nil, cty.NilVal, cty.NilVal, diags + } + + if !stateStoreConfigVal.IsWhollyKnown() { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Unknown values within state_store definition", + "The `terraform` configuration block should contain only concrete and static values. Another diagnostic should contain more information about which part of the configuration is problematic.")) + return nil, cty.NilVal, cty.NilVal, diags + } + + if m.Input() { + var err error + // TODO (SarahFrench/radeksimko) + // > Should we do this? + // > Could this accidentally prompt users to supply values in the nested provider block? + stateStoreConfigVal, err = m.inputForSchema(stateStoreConfigVal, schema.Body) + if err != nil { + diags = diags.Append(fmt.Errorf("Error asking for input to configure state store %q: %s", c.Type, err)) + return nil, cty.NilVal, cty.NilVal, diags + } + + // We get an unknown here if the if the user aborted input, but we can't + // turn that into a config value, so set it to null and let the provider + // handle it in PrepareConfig. + if !stateStoreConfigVal.IsKnown() { + stateStoreConfigVal = cty.NullVal(stateStoreConfigVal.Type()) + } + } + + // Validate and configure the provider + + // TODO (SarahFrench/radeksimko) : deal with marks + validateResp := provider.ValidateProviderConfig(providers.ValidateProviderConfigRequest{ + Config: providerConfigVal, + }) + diags = diags.Append(validateResp.Diagnostics) + if validateResp.Diagnostics.HasErrors() { + return nil, cty.NilVal, cty.NilVal, diags + } + + configureResp := provider.ConfigureProvider(providers.ConfigureProviderRequest{ + TerraformVersion: tfversion.String(), + Config: providerConfigVal, + // TODO ClientCapabilities? + }) + diags = diags.Append(configureResp.Diagnostics) + if configureResp.Diagnostics.HasErrors() { + return nil, cty.NilVal, cty.NilVal, diags + } + + // Validate Store Config + // TODO (SarahFrench/radeksimko) : deal with marks + validateStoreResp := provider.ValidateStateStoreConfig(providers.ValidateStateStoreConfigRequest{ + TypeName: c.Type, + Config: stateStoreConfigVal, + }) + diags = diags.Append(validateStoreResp.Diagnostics) + if validateStoreResp.Diagnostics.HasErrors() { + return nil, cty.NilVal, cty.NilVal, diags + } + + // Configure State Store + cfgStoreResp := provider.ConfigureStateStore(providers.ConfigureStateStoreRequest{ + TypeName: c.Type, + Config: stateStoreConfigVal, + }) + diags = diags.Append(cfgStoreResp.Diagnostics) + if cfgStoreResp.Diagnostics.HasErrors() { + return nil, cty.NilVal, cty.NilVal, diags + } + + // Now we have a fully configured state store, ready to be used. + // To make it usable we need to return it in a backend.Backend interface. + b, err := backendPluggable.NewPluggable(provider, c.Type) + if err != nil { + diags = diags.Append(err) + return nil, cty.NilVal, cty.NilVal, diags + } + + return b, stateStoreConfigVal, providerConfigVal, diags +} + // Helper method to get aliases from the enhanced backend and alias them // in the Meta service discovery. It's unfortunate that the Meta backend // is modifying the service discovery at this level, but the owner @@ -1742,6 +2259,41 @@ func (m *Meta) assertSupportedCloudInitOptions(mode cloud.ConfigChangeMode) tfdi return diags } +func (m *Meta) getStateStoreProviderFactory(config *configs.StateStore) (providers.Factory, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + if config.ProviderAddr.IsZero() { + // This should not happen; this data is populated when parsing config, + // even for builtin providers + panic(fmt.Sprintf("unknown provider while beginning to initialize state store %q from provider %q", + config.Type, + config.Provider.Name)) + } + + ctxOpts, err := m.contextOpts() + if err != nil { + diags = diags.Append(err) + return nil, diags + } + + factory, exists := ctxOpts.Providers[config.ProviderAddr] + if !exists { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Provider unavailable", + Detail: fmt.Sprintf("The provider %s (%q) is required to initialize the %q state store, but the matching provider factory is missing. This is a bug in Terraform and should be reported.", + config.Provider.Name, + config.ProviderAddr, + config.Type, + ), + Subject: &config.TypeRange, + }) + return nil, diags + } + + return factory, diags +} + //------------------------------------------------------------------- // Output constants and initialization code //------------------------------------------------------------------- @@ -1825,6 +2377,21 @@ hasn't changed and try again. At this point, no changes to your existing configuration or state have been made. ` +const errStateStoreInit = ` +Reason: %s +The "state store" is the interface that Terraform uses to store state when +performing operations on the local machine. If this message is showing up, +it means that the Terraform configuration you're using is using a custom +configuration for state storage in Terraform. +Changes to state store configurations require reinitialization. This allows +Terraform to set up the new configuration, copy existing state, etc. Please run +"terraform init" with either the "-reconfigure" or "-migrate-state" flags to +use the current configuration. +If the change reason above is incorrect, please verify your configuration +hasn't changed and try again. At this point, no changes to your existing +configuration or state have been made. +` + const errBackendInitCloud = ` Reason: %s. @@ -1845,6 +2412,14 @@ are usually due to simple file permission errors. Please look at the error above, resolve it, and try again. ` +const errStateStoreWorkspaceCreate = ` +Error creating the default workspace using pluggable state store %s: %s + +This could be a bug in the provider used for state storage, or a bug in +Terraform. Please file an issue with the provider developers before reporting +a bug for Terraform. +` + const outputBackendMigrateChange = ` Terraform detected that the backend type changed from %q to %q. ` diff --git a/internal/command/meta_backend_test.go b/internal/command/meta_backend_test.go index 014b43d00c25..a53a6bcbb9b8 100644 --- a/internal/command/meta_backend_test.go +++ b/internal/command/meta_backend_test.go @@ -13,6 +13,7 @@ import ( "strings" "testing" + "github.com/apparentlymart/go-versions/versions" "github.com/hashicorp/cli" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/backend" @@ -21,6 +22,8 @@ import ( "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/copy" + "github.com/hashicorp/terraform/internal/depsfile" + "github.com/hashicorp/terraform/internal/getproviders/providerreqs" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" testing_provider "github.com/hashicorp/terraform/internal/providers/testing" @@ -626,7 +629,7 @@ func TestMetaBackend_configureNewBackendWithStateExistingNoMigrate(t *testing.T) } // Saved backend state matching config -func TestMetaBackend_configuredUnchanged(t *testing.T) { +func TestMetaBackend_configuredBackendUnchanged(t *testing.T) { td := t.TempDir() testCopyDir(t, testFixturePath("backend-unchanged"), td) t.Chdir(td) @@ -2068,10 +2071,11 @@ func Test_determineInitReason(t *testing.T) { } // Newly configured state store +// Working directory has state_store in config but no preexisting backend state file // -// TODO(SarahFrench/radeksimko): currently this test only confirms that we're hitting the switch -// case for this scenario, and will need to be updated when that init feature is implemented. -func TestMetaBackend_configureNewStateStore(t *testing.T) { +// Tests that, during a non-init command, the command ends in with an error telling the user to run an init command +func TestMetaBackend_nonInitCommandInterrupted_uninitializedStateStore(t *testing.T) { + td := t.TempDir() testCopyDir(t, testFixturePath("state-store-new"), td) t.Chdir(td) @@ -2090,6 +2094,7 @@ func TestMetaBackend_configureNewStateStore(t *testing.T) { // // This imagines a provider called foo that contains // a pluggable state store implementation called bar. + pssName := "foo_bar" mock := &testing_provider.MockProvider{ GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{ Provider: providers.Schema{ @@ -2103,7 +2108,7 @@ func TestMetaBackend_configureNewStateStore(t *testing.T) { ResourceTypes: map[string]providers.Schema{}, ListResourceTypes: map[string]providers.Schema{}, StateStores: map[string]providers.Schema{ - "foo_bar": { + pssName: { Body: &configschema.Block{ Attributes: map[string]*configschema.Attribute{ "bar": { @@ -2116,24 +2121,65 @@ func TestMetaBackend_configureNewStateStore(t *testing.T) { }, }, } + mock.WriteStateBytesFn = func(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + // Workspaces exist once the artefact representing it is written + if _, exist := mock.MockStates[req.StateId]; !exist { + // Ensure non-nil map + if mock.MockStates == nil { + mock.MockStates = make(map[string]interface{}) + } + + mock.MockStates[req.StateId] = req.Bytes + } + return providers.WriteStateBytesResponse{ + Diagnostics: nil, // success + } + } + mock.ReadStateBytesFn = func(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + state := []byte{} + if v, exist := mock.MockStates[req.StateId]; exist { + if s, ok := v.([]byte); ok { + state = s + } + } + return providers.ReadStateBytesResponse{ + Bytes: state, + Diagnostics: nil, // success + } + } factory := func() (providers.Interface, error) { return mock, nil } - // Get the operations backend + // Create locks - these would normally be the locks derived from config + locks := depsfile.NewLocks() + constraint, err := providerreqs.ParseVersionConstraints(">9.0.0") + if err != nil { + t.Fatalf("test setup failed when making constraint: %s", err) + } + expectedVersionString := "9.9.9" + expectedProviderSource := "registry.terraform.io/my-org/foo" + locks.SetProvider( + addrs.MustParseProviderSourceString(expectedProviderSource), + versions.MustParseVersion(expectedVersionString), + constraint, + []providerreqs.Hash{"h1:foo"}, + ) + + // Act - get the operations backend _, beDiags := m.Backend(&BackendOpts{ - Init: true, + Init: false, StateStoreConfig: mod.StateStore, ProviderFactory: factory, + Locks: locks, }) if !beDiags.HasErrors() { - t.Fatal("expected an error to be returned during partial implementation of PSS") + t.Fatal("expected an error but got none") } - wantErr := "Configuring a state store for the first time is not implemented yet" - if !strings.Contains(beDiags.Err().Error(), wantErr) { - t.Fatalf("expected the returned error to contain %q, but got: %s", wantErr, beDiags.Err()) + expectedError := "State store initialization required, please run \"terraform init\": Reason: Initial configuration of the requested state_store \"foo_bar\" in provider foo (\"registry.terraform.io/my-org/foo\")" + if !strings.Contains(cleanString(beDiags.Err().Error()), expectedError) { + t.Fatalf("expected error to contain %s, but instead got: %s", expectedError, cleanString(beDiags.Err().Error())) } - } // Unsetting a saved state store @@ -2174,84 +2220,6 @@ func TestMetaBackend_configuredStateStoreUnset(t *testing.T) { } } -// Reconfiguring with an already configured state store. -// This should ignore the existing state_store config, and configure the new -// state store is if this is the first time. -// -// TODO(SarahFrench/radeksimko): currently this test only confirms that we're hitting the switch -// case for this scenario, and will need to be updated when that init feature is implemented. -func TestMetaBackend_reconfigureStateStoreChange(t *testing.T) { - td := t.TempDir() - testCopyDir(t, testFixturePath("state-store-reconfigure"), td) - t.Chdir(td) - - // Setup the meta - m := testMetaBackend(t, nil) - m.AllowExperimentalFeatures = true - - // this should not ask for input - m.input = false - - // cli flag -reconfigure - m.reconfigure = true - - // Get the state store's config - mod, loadDiags := m.loadSingleModule(td) - if loadDiags.HasErrors() { - t.Fatalf("unexpected error when loading test config: %s", loadDiags.Err()) - } - - // Get mock provider factory to be used during init - // - // This imagines a provider called foo that contains - // a pluggable state store implementation called bar. - mock := &testing_provider.MockProvider{ - GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{ - Provider: providers.Schema{ - Body: &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "region": {Type: cty.String, Optional: true}, - }, - }, - }, - DataSources: map[string]providers.Schema{}, - ResourceTypes: map[string]providers.Schema{}, - ListResourceTypes: map[string]providers.Schema{}, - StateStores: map[string]providers.Schema{ - "foo_bar": { - Body: &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "bar": { - Type: cty.String, - Required: true, - }, - }, - }, - }, - }, - }, - } - factory := func() (providers.Interface, error) { - return mock, nil - } - - // Get the operations backend - _, beDiags := m.Backend(&BackendOpts{ - Init: true, - StateStoreConfig: mod.StateStore, - ProviderFactory: factory, - }) - - if !beDiags.HasErrors() { - t.Fatal("expected an error to be returned during partial implementation of PSS") - } - wantErr := "Configuring a state store for the first time is not implemented yet" - if !strings.Contains(beDiags.Err().Error(), wantErr) { - t.Fatalf("expected the returned error to contain %q, but got: %s", wantErr, beDiags.Err()) - } - -} - // Changing a configured state store // // TODO(SarahFrench/radeksimko): currently this test only confirms that we're hitting the switch diff --git a/internal/command/meta_dependencies.go b/internal/command/meta_dependencies.go index e7f213e43dfd..b84afecf3afb 100644 --- a/internal/command/meta_dependencies.go +++ b/internal/command/meta_dependencies.go @@ -66,6 +66,43 @@ func (m *Meta) replaceLockedDependencies(new *depsfile.Locks) tfdiags.Diagnostic return depsfile.SaveLocksToFile(new, dependencyLockFilename) } +// mergeLockedDependencies combines two sets of locks. The 'base' locks are copied, and any providers +// present in the additional locks that aren't present in the base are added to that copy. The merged +// combination is returned. +// +// If you're combining locks derived from config with other locks (from state or deps locks file), then +// the config locks need to be the first argument to ensure that the merged locks contain any +// version constraints. Version constraint data is only present in configuration. +// This allows code in the init command to download providers in separate phases and +// keep the lock file updated accurately after each phase. +// +// This method supports downloading providers in 2 steps, and is used during the second download step and +// while updating the dependency lock file. +func (m *Meta) mergeLockedDependencies(baseLocks, additionalLocks *depsfile.Locks) *depsfile.Locks { + + mergedLocks := baseLocks.DeepCopy() + + // Append locks derived from the state to locks derived from config. + for _, lock := range additionalLocks.AllProviders() { + match := mergedLocks.Provider(lock.Provider()) + if match != nil { + log.Printf("[TRACE] Ignoring provider %s version %s in appendLockedDependencies; lock file contains %s version %s already", + lock.Provider(), + lock.Version(), + match.Provider(), + match.Version(), + ) + } else { + // This is a new provider now present in the lockfile yet + log.Printf("[DEBUG] Appending provider %s to the lock file", lock.Provider()) + mergedLocks.SetProvider(lock.Provider(), lock.Version(), lock.VersionConstraints(), lock.AllHashes()) + } + } + + // Override the locks file with the new combination of locks + return mergedLocks +} + // annotateDependencyLocksWithOverrides modifies the given Locks object in-place // to track as overridden any provider address that's subject to testing // overrides, development overrides, or "unmanaged provider" status. diff --git a/internal/command/meta_dependencies_test.go b/internal/command/meta_dependencies_test.go new file mode 100644 index 000000000000..b245648867f1 --- /dev/null +++ b/internal/command/meta_dependencies_test.go @@ -0,0 +1,151 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package command + +import ( + "testing" + + "github.com/apparentlymart/go-versions/versions" + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/cli" + tfaddr "github.com/hashicorp/terraform-registry-address" + "github.com/hashicorp/terraform/internal/depsfile" + "github.com/hashicorp/terraform/internal/getproviders/providerreqs" +) + +// This tests combining locks from config and state. Locks derived from state are always unconstrained, i.e. no version constraint data, +// so this test +func Test_mergeLockedDependencies_config_and_state(t *testing.T) { + + providerA := tfaddr.NewProvider(tfaddr.DefaultProviderRegistryHost, "my-org", "providerA") + providerB := tfaddr.NewProvider(tfaddr.DefaultProviderRegistryHost, "my-org", "providerB") + v1_0_0 := providerreqs.MustParseVersion("1.0.0") + versionConstraintv1, _ := providerreqs.ParseVersionConstraints("1.0.0") + hashesProviderA := []providerreqs.Hash{providerreqs.MustParseHash("providerA:this-is-providerA")} + hashesProviderB := []providerreqs.Hash{providerreqs.MustParseHash("providerB:this-is-providerB")} + + var versionUnconstrained providerreqs.VersionConstraints = nil + noVersion := versions.Version{} + + cases := map[string]struct { + configLocks *depsfile.Locks + stateLocks *depsfile.Locks + expectedLocks *depsfile.Locks + }{ + "no locks when all inputs empty": { + configLocks: depsfile.NewLocks(), + stateLocks: depsfile.NewLocks(), + expectedLocks: depsfile.NewLocks(), + }, + "when provider only described in config, output locks have matching constraints": { + configLocks: func() *depsfile.Locks { + configLocks := depsfile.NewLocks() + configLocks.SetProvider(providerA, v1_0_0, versionConstraintv1, hashesProviderA) + return configLocks + }(), + stateLocks: depsfile.NewLocks(), + expectedLocks: func() *depsfile.Locks { + combinedLocks := depsfile.NewLocks() + combinedLocks.SetProvider(providerA, v1_0_0, versionConstraintv1, hashesProviderA) + return combinedLocks + }(), + }, + "when provider only described in state, output locks are unconstrained": { + configLocks: depsfile.NewLocks(), + stateLocks: func() *depsfile.Locks { + stateLocks := depsfile.NewLocks() + stateLocks.SetProvider(providerA, noVersion, versionUnconstrained, hashesProviderA) + return stateLocks + }(), + expectedLocks: func() *depsfile.Locks { + combinedLocks := depsfile.NewLocks() + combinedLocks.SetProvider(providerA, noVersion, versionUnconstrained, hashesProviderA) + return combinedLocks + }(), + }, + "different providers present in state and config are combined, with version constraints kept on config providers": { + configLocks: func() *depsfile.Locks { + configLocks := depsfile.NewLocks() + configLocks.SetProvider(providerA, v1_0_0, versionConstraintv1, hashesProviderA) + return configLocks + }(), + stateLocks: func() *depsfile.Locks { + stateLocks := depsfile.NewLocks() + + // Imagine that the state locks contain: + // 1) provider for resources in the config + stateLocks.SetProvider(providerA, noVersion, versionUnconstrained, hashesProviderA) + + // 2) also, a provider that's deleted from the config and only present in state + stateLocks.SetProvider(providerB, noVersion, versionUnconstrained, hashesProviderB) + + return stateLocks + }(), + expectedLocks: func() *depsfile.Locks { + combinedLocks := depsfile.NewLocks() + combinedLocks.SetProvider(providerA, v1_0_0, versionConstraintv1, hashesProviderA) // version constraint preserved + combinedLocks.SetProvider(providerB, noVersion, versionUnconstrained, hashesProviderB) // sourced from state only + return combinedLocks + }(), + }, + } + + for tn, tc := range cases { + t.Run(tn, func(t *testing.T) { + // Use tmp dir as we're creating lock files in the test + td := t.TempDir() + t.Chdir(td) + + ui := new(cli.MockUi) + view, _ := testView(t) + + m := Meta{ + Ui: ui, + View: view, + } + + // Code under test - combine deps from state with prior deps from config + // mergedLocks := m.mergeLockedDependencies(tc.configLocks, tc.stateLocks) + mergedLocks := m.mergeLockedDependencies(tc.configLocks, tc.stateLocks) + + // We cannot use (l *depsfile.Locks) Equal here as it doesn't compare version constraints + // Instead, inspect entries directly + if len(mergedLocks.AllProviders()) != len(tc.expectedLocks.AllProviders()) { + t.Fatalf("expected merged dependencies to include %d providers, but got %d:\n %#v", + len(tc.expectedLocks.AllProviders()), + len(mergedLocks.AllProviders()), + mergedLocks.AllProviders(), + ) + } + for _, lock := range tc.expectedLocks.AllProviders() { + match := mergedLocks.Provider(lock.Provider()) + if match == nil { + t.Fatalf("expected merged dependencies to include provider %s, but it's missing", lock.Provider()) + } + if len(match.VersionConstraints()) != len(lock.VersionConstraints()) { + t.Fatalf("detected a problem with version constraints for provider %s, got: %d, want %d", + lock.Provider(), + len(match.VersionConstraints()), + len(lock.VersionConstraints()), + ) + } + if len(match.VersionConstraints()) > 0 && len(lock.VersionConstraints()) > 0 { + gotConstraints := match.VersionConstraints()[0] + wantConstraints := lock.VersionConstraints()[0] + + if gotConstraints.Boundary.String() != wantConstraints.Boundary.String() { + t.Fatalf("expected merged dependencies to include provider %s with version constraint %v, but instead got %v", + lock.Provider(), + gotConstraints.Boundary.String(), + wantConstraints.Boundary.String(), + ) + } + } + } + if diff := cmp.Diff(tc.expectedLocks, mergedLocks); diff != "" { + t.Errorf("difference in file contents detected\n%s", diff) + } + }) + } +} diff --git a/internal/command/testdata/init-provider-download/config-and-state-different-providers/main.tf b/internal/command/testdata/init-provider-download/config-and-state-different-providers/main.tf new file mode 100644 index 000000000000..f0687030bb2f --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-and-state-different-providers/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + null = { + source = "hashicorp/null" + version = "<9.0.0" + } + } + + backend "local" { + path = "./state-using-random-provider.tfstate" + } +} + +resource "null_resource" "null" {} diff --git a/internal/command/testdata/init-provider-download/config-and-state-different-providers/state-using-random-provider.tfstate b/internal/command/testdata/init-provider-download/config-and-state-different-providers/state-using-random-provider.tfstate new file mode 100644 index 000000000000..76b543b06af6 --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-and-state-different-providers/state-using-random-provider.tfstate @@ -0,0 +1,28 @@ +{ + "version": 4, + "terraform_version": "1.14.0", + "serial": 1, + "lineage": "foobar", + "resources": [ + { + "mode": "managed", + "type": "random_pet", + "name": "maurice", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "sassy-ferret", + "keepers": null, + "length": 2, + "prefix": null, + "separator": "-" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/internal/command/testdata/init-provider-download/config-and-state-same-providers/main.tf b/internal/command/testdata/init-provider-download/config-and-state-same-providers/main.tf new file mode 100644 index 000000000000..d5857489d6de --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-and-state-same-providers/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + random = { + source = "hashicorp/random" + version = "<9.0.0" + } + } + + backend "local" { + path = "./state-using-random-provider.tfstate" + } +} + +resource "random_pet" "maurice" {} diff --git a/internal/command/testdata/init-provider-download/config-and-state-same-providers/state-using-random-provider.tfstate b/internal/command/testdata/init-provider-download/config-and-state-same-providers/state-using-random-provider.tfstate new file mode 100644 index 000000000000..76b543b06af6 --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-and-state-same-providers/state-using-random-provider.tfstate @@ -0,0 +1,28 @@ +{ + "version": 4, + "terraform_version": "1.14.0", + "serial": 1, + "lineage": "foobar", + "resources": [ + { + "mode": "managed", + "type": "random_pet", + "name": "maurice", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "sassy-ferret", + "keepers": null, + "length": 2, + "prefix": null, + "separator": "-" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/.terraform.lock.hcl b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/.terraform.lock.hcl new file mode 100644 index 000000000000..2140e1a14471 --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/.terraform.lock.hcl @@ -0,0 +1,6 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/random" { + version = "1.0.0" +} diff --git a/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/main.tf b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/main.tf new file mode 100644 index 000000000000..d5857489d6de --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + random = { + source = "hashicorp/random" + version = "<9.0.0" + } + } + + backend "local" { + path = "./state-using-random-provider.tfstate" + } +} + +resource "random_pet" "maurice" {} diff --git a/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/state-using-random-provider.tfstate b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/state-using-random-provider.tfstate new file mode 100644 index 000000000000..76b543b06af6 --- /dev/null +++ b/internal/command/testdata/init-provider-download/config-state-file-and-lockfile/state-using-random-provider.tfstate @@ -0,0 +1,28 @@ +{ + "version": 4, + "terraform_version": "1.14.0", + "serial": 1, + "lineage": "foobar", + "resources": [ + { + "mode": "managed", + "type": "random_pet", + "name": "maurice", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "sassy-ferret", + "keepers": null, + "length": 2, + "prefix": null, + "separator": "-" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/internal/command/testdata/init-provider-download/state-file-only/main.tf b/internal/command/testdata/init-provider-download/state-file-only/main.tf new file mode 100644 index 000000000000..d568a66bf2ed --- /dev/null +++ b/internal/command/testdata/init-provider-download/state-file-only/main.tf @@ -0,0 +1,5 @@ +terraform { + backend "local" { + path = "./state-using-random-provider.tfstate" + } +} diff --git a/internal/command/testdata/init-provider-download/state-file-only/state-using-random-provider.tfstate b/internal/command/testdata/init-provider-download/state-file-only/state-using-random-provider.tfstate new file mode 100644 index 000000000000..76b543b06af6 --- /dev/null +++ b/internal/command/testdata/init-provider-download/state-file-only/state-using-random-provider.tfstate @@ -0,0 +1,28 @@ +{ + "version": 4, + "terraform_version": "1.14.0", + "serial": 1, + "lineage": "foobar", + "resources": [ + { + "mode": "managed", + "type": "random_pet", + "name": "maurice", + "provider": "provider[\"registry.terraform.io/hashicorp/random\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "sassy-ferret", + "keepers": null, + "length": 2, + "prefix": null, + "separator": "-" + }, + "sensitive_attributes": [], + "identity_schema_version": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/internal/command/testdata/init-with-state-store/main.tf b/internal/command/testdata/init-with-state-store/main.tf index a4042b401b17..604feb44fed7 100644 --- a/internal/command/testdata/init-with-state-store/main.tf +++ b/internal/command/testdata/init-with-state-store/main.tf @@ -1,5 +1,11 @@ terraform { - state_store "foo_foo" { + required_providers { + test = { + source = "hashicorp/test" + } + } + state_store "test_store" { + provider "test" {} } } diff --git a/internal/command/testdata/state-store-new/main.tf b/internal/command/testdata/state-store-new/main.tf index 72643dbb9505..6ae0ba26acb7 100644 --- a/internal/command/testdata/state-store-new/main.tf +++ b/internal/command/testdata/state-store-new/main.tf @@ -5,7 +5,9 @@ terraform { } } state_store "foo_bar" { - provider "foo" {} + provider "foo" { + region = "mars" + } bar = "foobar" } diff --git a/internal/command/testdata/state-store-reconfigure/.terraform/terraform.tfstate b/internal/command/testdata/state-store-reconfigure/.terraform/terraform.tfstate index a59e231faa03..365916938654 100644 --- a/internal/command/testdata/state-store-reconfigure/.terraform/terraform.tfstate +++ b/internal/command/testdata/state-store-reconfigure/.terraform/terraform.tfstate @@ -5,7 +5,7 @@ "state_store": { "type": "foo_bar", "config": { - "bar": "old-value" + "value": "old-value" }, "provider": { "version": "1.2.3", diff --git a/internal/command/testdata/state-store-reconfigure/main.tf b/internal/command/testdata/state-store-reconfigure/main.tf index 49184a175b6d..085c2f36d3f1 100644 --- a/internal/command/testdata/state-store-reconfigure/main.tf +++ b/internal/command/testdata/state-store-reconfigure/main.tf @@ -1,12 +1,12 @@ terraform { required_providers { - foo = { - source = "my-org/foo" + test = { + source = "hashicorp/test" } } - state_store "foo_bar" { - provider "foo" {} + state_store "test_store" { + provider "test" {} - bar = "changed-value" # changed versus backend state file + value = "changed-value" # changed versus backend state file } } diff --git a/internal/command/views/init.go b/internal/command/views/init.go index d228cb81d566..c97d2f7ffcf5 100644 --- a/internal/command/views/init.go +++ b/internal/command/views/init.go @@ -182,13 +182,21 @@ var MessageRegistry map[InitMessageCode]InitMessage = map[InitMessageCode]InitMe HumanValue: "\n[reset][bold]Initializing the backend...", JSONValue: "Initializing the backend...", }, + "initializing_state_store_message": { + HumanValue: "\n[reset][bold]Initializing the state store...", + JSONValue: "Initializing the state store...", + }, "initializing_provider_plugin_message": { HumanValue: "\n[reset][bold]Initializing provider plugins...", JSONValue: "Initializing provider plugins...", }, - "initializing_state_store_message": { - HumanValue: "\n[reset][bold]Initializing the state store...", - JSONValue: "Initializing the state store...", + "initializing_provider_plugin_from_config_message": { + HumanValue: "\n[reset][bold]Initializing provider plugins found in the configuration...", + JSONValue: "Initializing provider plugins found in the configuration...", + }, + "initializing_provider_plugin_from_state_message": { + HumanValue: "\n[reset][bold]Initializing provider plugins found in the state...", + JSONValue: "Initializing provider plugins found in the state...", }, "dependencies_lock_changes_info": { HumanValue: dependenciesLockChangesInfo, @@ -210,6 +218,10 @@ var MessageRegistry map[InitMessageCode]InitMessage = map[InitMessageCode]InitMe HumanValue: "- Reusing previous version of %s from the dependency lock file", JSONValue: "%s: Reusing previous version from the dependency lock file", }, + "reusing_version_during_state_provider_init": { + HumanValue: "- Reusing previous version of %s", + JSONValue: "%s: Reusing previous version of %s", + }, "finding_matching_version_message": { HumanValue: "- Finding %s versions matching %q...", JSONValue: "Finding matching versions for provider: %s, version_constraint: %q", @@ -271,6 +283,14 @@ const ( DependenciesLockChangesInfo InitMessageCode = "dependencies_lock_changes_info" //// Message codes below are ONLY used INTERNALLY (for now) + + // InitializingProviderPluginFromConfigMessage indicates the beginning of installing of providers described in configuration + InitializingProviderPluginFromConfigMessage InitMessageCode = "initializing_provider_plugin_from_config_message" + // InitializingProviderPluginFromStateMessage indicates the beginning of installing of providers described in state + InitializingProviderPluginFromStateMessage InitMessageCode = "initializing_provider_plugin_from_state_message" + // DependenciesLockPendingChangesInfo indicates when a provider installation step will reuse a provider from a previous installation step in the current operation + ReusingVersionIdentifiedFromConfig InitMessageCode = "reusing_version_during_state_provider_init" + // InitConfigError indicates problems encountered during initialisation InitConfigError InitMessageCode = "init_config_error" // FindingMatchingVersionMessage indicates that Terraform is looking for a provider version that matches the constraint during installation diff --git a/internal/configs/parser_config.go b/internal/configs/parser_config.go index fa72ba7f9c05..4047fe1db83a 100644 --- a/internal/configs/parser_config.go +++ b/internal/configs/parser_config.go @@ -104,14 +104,6 @@ func parseConfigFile(body hcl.Body, diags hcl.Diagnostics, override, allowExperi switch block.Type { case "terraform": - // TODO: Update once pluggable state store is out of experimental phase - if allowExperiments { - terraformBlockSchema.Blocks = append(terraformBlockSchema.Blocks, - hcl.BlockHeaderSchema{ - Type: "state_store", - LabelNames: []string{"type"}, - }) - } content, contentDiags := block.Body.Content(terraformBlockSchema) diags = append(diags, contentDiags...) @@ -394,9 +386,10 @@ var terraformBlockSchema = &hcl.BodySchema{ { Type: "required_providers", }, - // NOTE: An entry for state_store is not present here - // because we conditionally add it in the calling code - // depending on whether experiments are enabled or not. + { + Type: "state_store", + LabelNames: []string{"type"}, + }, { Type: "provider_meta", LabelNames: []string{"provider"}, diff --git a/internal/configs/state_store.go b/internal/configs/state_store.go index aa12509095c3..16da71827daa 100644 --- a/internal/configs/state_store.go +++ b/internal/configs/state_store.go @@ -116,8 +116,9 @@ func resolveStateStoreProviderType(requiredProviders map[string]*RequiredProvide diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "Missing entry in required_providers", - Detail: fmt.Sprintf("The provider used for state storage must have a matching entry in required_providers. Please add an entry for provider %q", - stateStore.Provider.Name), + Detail: fmt.Sprintf("The provider used for state storage must have a matching entry in required_providers. Please add an entry for provider %s (%q)", + stateStore.Provider.Name, + stateStore.ProviderAddr), Subject: &stateStore.DeclRange, }) return tfaddr.Provider{}, diags diff --git a/internal/getproviders/providerreqs/version.go b/internal/getproviders/providerreqs/version.go index 579eceb9ac4c..2fc15fc499de 100644 --- a/internal/getproviders/providerreqs/version.go +++ b/internal/getproviders/providerreqs/version.go @@ -20,6 +20,8 @@ import ( "github.com/apparentlymart/go-versions/versions" "github.com/apparentlymart/go-versions/versions/constraints" + "github.com/hashicorp/go-version" + "github.com/hashicorp/terraform/internal/addrs" ) @@ -86,6 +88,12 @@ func ParseVersion(str string) (Version, error) { return versions.ParseVersion(str) } +// GoVersionFromVersion converts a Version from the providerreqs package +// into a Version from the hashicorp/go-version module. +func GoVersionFromVersion(v Version) (*version.Version, error) { + return version.NewVersion(v.String()) +} + // MustParseVersion is a variant of ParseVersion that panics if it encounters // an error while parsing. func MustParseVersion(str string) Version { diff --git a/internal/grpcwrap/provider6.go b/internal/grpcwrap/provider6.go index 64c3a62ce822..70d52124f85d 100644 --- a/internal/grpcwrap/provider6.go +++ b/internal/grpcwrap/provider6.go @@ -918,6 +918,14 @@ func (p *provider6) ConfigureStateStore(ctx context.Context, req *tfplugin6.Conf panic("not implemented") } +func (p *provider6) ReadStateBytes(req *tfplugin6.ReadStateBytes_Request, srv tfplugin6.Provider_ReadStateBytesServer) error { + panic("not implemented") +} + +func (p *provider6) WriteStateBytes(srv tfplugin6.Provider_WriteStateBytesServer) error { + panic("not implemented") +} + func (p *provider6) GetStates(ctx context.Context, req *tfplugin6.GetStates_Request) (*tfplugin6.GetStates_Response, error) { panic("not implemented") } diff --git a/internal/legacy/go.mod b/internal/legacy/go.mod index 928782be4757..21af27b3c9e6 100644 --- a/internal/legacy/go.mod +++ b/internal/legacy/go.mod @@ -2,7 +2,7 @@ module github.com/hashicorp/terraform/internal/legacy replace github.com/hashicorp/terraform => ../.. -go 1.24.5 +go 1.25 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc diff --git a/internal/plugin/grpc_provider.go b/internal/plugin/grpc_provider.go index 323897406cf9..541a48d0c356 100644 --- a/internal/plugin/grpc_provider.go +++ b/internal/plugin/grpc_provider.go @@ -1418,6 +1418,14 @@ func (p *GRPCProvider) ConfigureStateStore(r providers.ConfigureStateStoreReques panic("not implemented") } +func (p *GRPCProvider) ReadStateBytes(r providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + panic("not implemented") +} + +func (p *GRPCProvider) WriteStateBytes(r providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + panic("not implemented") +} + func (p *GRPCProvider) GetStates(r providers.GetStatesRequest) providers.GetStatesResponse { panic("not implemented") } diff --git a/internal/plugin6/grpc_provider.go b/internal/plugin6/grpc_provider.go index e7c46797b465..61ca88d8863c 100644 --- a/internal/plugin6/grpc_provider.go +++ b/internal/plugin6/grpc_provider.go @@ -4,6 +4,7 @@ package plugin6 import ( + "bytes" "context" "errors" "fmt" @@ -1478,6 +1479,170 @@ func (p *GRPCProvider) ConfigureStateStore(r providers.ConfigureStateStoreReques return resp } +func (p *GRPCProvider) ReadStateBytes(r providers.ReadStateBytesRequest) (resp providers.ReadStateBytesResponse) { + logger.Trace("GRPCProvider.v6: ReadStateBytes") + + schema := p.GetProviderSchema() + if schema.Diagnostics.HasErrors() { + resp.Diagnostics = schema.Diagnostics + return resp + } + + if _, ok := schema.StateStores[r.TypeName]; !ok { + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("unknown state store type %q", r.TypeName)) + return resp + } + + protoReq := &proto6.ReadStateBytes_Request{ + TypeName: r.TypeName, + StateId: r.StateId, + } + + // Start the streaming RPC with a context. The context will be cancelled + // when this function returns, which will stop the stream if it is still + // running. + ctx, cancel := context.WithCancel(p.ctx) + defer cancel() + + client, err := p.client.ReadStateBytes(ctx, protoReq) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + return resp + } + + buf := &bytes.Buffer{} + var expectedTotalLength int + for { + chunk, err := client.Recv() + if err == io.EOF { + // No chunk is returned alongside an EOF. + // And as EOF is a sentinel error it isn't wrapped as a diagnostic. + break + } + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + break + } + resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(chunk.Diagnostics)) + if resp.Diagnostics.HasErrors() { + // If we have errors, we stop processing and return early + break + } + + if expectedTotalLength == 0 { + expectedTotalLength = int(chunk.TotalLength) + } + logger.Trace("GRPCProvider.v6: ReadStateBytes: received chunk for range", chunk.Range) + + n, err := buf.Write(chunk.Bytes) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(err) + break + } + logger.Trace("GRPCProvider.v6: ReadStateBytes: read bytes of a chunk", n) + } + + if resp.Diagnostics.HasErrors() { + logger.Trace("GRPCProvider.v6: ReadStateBytes: experienced an error when receiving state data from the provider", resp.Diagnostics.Err()) + return resp + } + + if buf.Len() != expectedTotalLength { + logger.Trace("GRPCProvider.v6: ReadStateBytes: received %d bytes but expected the total bytes to be %d.", buf.Len(), expectedTotalLength) + + err = fmt.Errorf("expected state file of total %d bytes, received %d bytes", + expectedTotalLength, buf.Len()) + resp.Diagnostics = resp.Diagnostics.Append(err) + return resp + } + + // We're done, so close the stream + logger.Trace("GRPCProvider.v6: ReadStateBytes: received all chunks, total bytes: ", buf.Len()) + err = client.CloseSend() + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + return resp + } + + // Add the state data in the response once we know there are no errors + resp.Bytes = buf.Bytes() + + return resp +} + +func (p *GRPCProvider) WriteStateBytes(r providers.WriteStateBytesRequest) (resp providers.WriteStateBytesResponse) { + logger.Trace("GRPCProvider.v6: WriteStateBytes") + + schema := p.GetProviderSchema() + if schema.Diagnostics.HasErrors() { + resp.Diagnostics = schema.Diagnostics + return resp + } + + if _, ok := schema.StateStores[r.TypeName]; !ok { + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("unknown state store type %q", r.TypeName)) + return resp + } + + // Start the streaming RPC with a context. The context will be cancelled + // when this function returns, which will stop the stream if it is still + // running. + ctx, cancel := context.WithCancel(p.ctx) + defer cancel() + + // TODO: Configurable chunk size + chunkSize := 4 * 1_000_000 // 4MB + + client, err := p.client.WriteStateBytes(ctx) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + return resp + } + + buf := bytes.NewBuffer(r.Bytes) + var totalLength int64 = int64(len(r.Bytes)) + var totalBytesProcessed int + for { + chunk := buf.Next(chunkSize) + + if len(chunk) == 0 { + // The previous iteration read the last of the data. Now we finish up. + protoResp, err := client.CloseAndRecv() + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + return resp + } + resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) + if resp.Diagnostics.HasErrors() { + return resp + } + break + } + + // There is more data to write + protoReq := &proto6.WriteStateBytes_RequestChunk{ + TypeName: r.TypeName, + StateId: r.StateId, + Bytes: chunk, + TotalLength: totalLength, + Range: &proto6.StateRange{ + Start: int64(totalBytesProcessed), + End: int64(totalBytesProcessed + len(chunk)), + }, + } + err = client.Send(protoReq) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(grpcErr(err)) + return resp + } + + // Track progress before next iteration + totalBytesProcessed += len(chunk) + } + + return resp +} + func (p *GRPCProvider) GetStates(r providers.GetStatesRequest) (resp providers.GetStatesResponse) { logger.Trace("GRPCProvider.v6: GetStates") diff --git a/internal/plugin6/grpc_provider_test.go b/internal/plugin6/grpc_provider_test.go index cc5a4251cea2..ab029d4d3773 100644 --- a/internal/plugin6/grpc_provider_test.go +++ b/internal/plugin6/grpc_provider_test.go @@ -6,6 +6,7 @@ package plugin6 import ( "bytes" "context" + "errors" "fmt" "io" "testing" @@ -21,6 +22,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/backend" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/configs/hcl2shim" "github.com/hashicorp/terraform/internal/plans" @@ -61,6 +63,16 @@ func mockProviderClient(t *testing.T) *mockproto.MockProviderClient { return client } +func mockReadStateBytesClient(t *testing.T) *mockproto.MockProvider_ReadStateBytesClient { + ctrl := gomock.NewController(t) + return mockproto.NewMockProvider_ReadStateBytesClient(ctrl) +} + +func mockWriteStateBytesClient(t *testing.T) *mockproto.MockProvider_WriteStateBytesClient { + ctrl := gomock.NewController(t) + return mockproto.NewMockProvider_WriteStateBytesClient(ctrl) +} + func checkDiags(t *testing.T, d tfdiags.Diagnostics) { t.Helper() if d.HasErrors() { @@ -3481,3 +3493,591 @@ func TestGRPCProvider_DeleteState(t *testing.T) { } }) } + +func TestGRPCProvider_ReadStateBytes(t *testing.T) { + t.Run("can process multiple chunks", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Call to ReadStateBytes + // > Assert the arguments received + // > Define the returned mock client + expectedReq := &proto.ReadStateBytes_Request{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + } + mockReadBytesClient := mockReadStateBytesClient(t) + client.EXPECT().ReadStateBytes( + gomock.Any(), + gomock.Eq(expectedReq), + ).Return(mockReadBytesClient, nil) + + // Define what will be returned by each call to Recv + chunks := []string{"hello", "world"} + totalLength := len(chunks[0]) + len(chunks[1]) + mockResp := map[int]struct { + resp *proto.ReadStateBytes_Response + err error + }{ + 0: { + resp: &proto.ReadStateBytes_Response{ + Bytes: []byte(chunks[0]), + TotalLength: int64(totalLength), + Range: &proto.StateRange{ + Start: 0, + End: int64(len(chunks[0])), + }, + }, + err: nil, + }, + 1: { + resp: &proto.ReadStateBytes_Response{ + Bytes: []byte(chunks[1]), + TotalLength: int64(totalLength), + Range: &proto.StateRange{ + Start: int64(len(chunks[0])), + End: int64(len(chunks[1])), + }, + }, + err: nil, + }, + 2: { + resp: &proto.ReadStateBytes_Response{}, + err: io.EOF, + }, + } + var count int + mockReadBytesClient.EXPECT().Recv().DoAndReturn(func() (*proto.ReadStateBytes_Response, error) { + ret := mockResp[count] + count++ + return ret.resp, ret.err + }).Times(3) + + // Act + request := providers.ReadStateBytesRequest{ + TypeName: expectedReq.TypeName, + StateId: expectedReq.StateId, + } + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiags(t, resp.Diagnostics) + if string(resp.Bytes) != "helloworld" { + t.Fatalf("expected data to be %q, got: %q", "helloworld", string(resp.Bytes)) + } + }) + + t.Run("an error diagnostic is returned when final length does not match expectations", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Call to ReadStateBytes + // > Assert the arguments received + // > Define the returned mock client + mockReadBytesClient := mockReadStateBytesClient(t) + expectedReq := &proto.ReadStateBytes_Request{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + } + client.EXPECT().ReadStateBytes( + gomock.Any(), + gomock.Eq(expectedReq), + ).Return(mockReadBytesClient, nil) + + // Define what will be returned by each call to Recv + chunks := []string{"hello", "world"} + var incorrectLength int64 = 999 + correctLength := len(chunks[0]) + len(chunks[1]) + mockResp := map[int]struct { + resp *proto.ReadStateBytes_Response + err error + }{ + 0: { + resp: &proto.ReadStateBytes_Response{ + Bytes: []byte(chunks[0]), + TotalLength: incorrectLength, + Range: &proto.StateRange{ + Start: 0, + End: int64(len(chunks[0])), + }, + }, + err: nil, + }, + 1: { + resp: &proto.ReadStateBytes_Response{ + Bytes: []byte(chunks[1]), + TotalLength: incorrectLength, + Range: &proto.StateRange{ + Start: int64(len(chunks[0])), + End: int64(len(chunks[1])), + }, + }, + err: nil, + }, + 2: { + resp: &proto.ReadStateBytes_Response{}, + err: io.EOF, + }, + } + var count int + mockReadBytesClient.EXPECT().Recv().DoAndReturn(func() (*proto.ReadStateBytes_Response, error) { + ret := mockResp[count] + count++ + return ret.resp, ret.err + }).Times(3) + + // Act + request := providers.ReadStateBytesRequest{ + TypeName: expectedReq.TypeName, + StateId: expectedReq.StateId, + } + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + expectedErr := fmt.Sprintf("expected state file of total %d bytes, received %d bytes", incorrectLength, correctLength) + if resp.Diagnostics.Err().Error() != expectedErr { + t.Fatalf("expected error diagnostic %q, but got: %q", expectedErr, resp.Diagnostics.Err()) + } + if len(resp.Bytes) != 0 { + t.Fatalf("expected data to be omitted in error condition, but got: %q", string(resp.Bytes)) + } + }) + + t.Run("an error diagnostic is returned when store type does not exist", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // In this scenario the method returns before the call to the + // ReadStateBytes RPC, so no mocking needed + + badStoreType := "doesnt_exist" + request := providers.ReadStateBytesRequest{ + TypeName: badStoreType, + StateId: backend.DefaultStateName, + } + + // Act + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + expectedErr := fmt.Sprintf("unknown state store type %q", badStoreType) + if resp.Diagnostics.Err().Error() != expectedErr { + t.Fatalf("expected error diagnostic %q, but got: %q", expectedErr, resp.Diagnostics.Err()) + } + if len(resp.Bytes) != 0 { + t.Fatalf("expected data to be omitted in error condition, but got: %q", string(resp.Bytes)) + } + }) + + t.Run("error diagnostics from the provider are returned", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Call to ReadStateBytes + // > Assert the arguments received + // > Define the returned mock client + mockReadBytesClient := mockReadStateBytesClient(t) + + expectedReq := &proto.ReadStateBytes_Request{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + } + client.EXPECT().ReadStateBytes( + gomock.Any(), + gomock.Eq(expectedReq), + ).Return(mockReadBytesClient, nil) + + // Define what will be returned by each call to Recv + mockReadBytesClient.EXPECT().Recv().Return(&proto.ReadStateBytes_Response{ + Diagnostics: []*proto.Diagnostic{ + &proto.Diagnostic{ + Severity: proto.Diagnostic_ERROR, + Summary: "Error from test", + Detail: "This error is forced by the test case", + }, + }, + }, nil) + + // Act + request := providers.ReadStateBytesRequest{ + TypeName: expectedReq.TypeName, + StateId: expectedReq.StateId, + } + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + expectedErr := "Error from test: This error is forced by the test case" + if resp.Diagnostics.Err().Error() != expectedErr { + t.Fatalf("expected error diagnostic %q, but got: %q", expectedErr, resp.Diagnostics.Err()) + } + if len(resp.Bytes) != 0 { + t.Fatalf("expected data to be omitted in error condition, but got: %q", string(resp.Bytes)) + } + }) + + t.Run("warning diagnostics from the provider are returned", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Call to ReadStateBytes + // > Assert the arguments received + // > Define the returned mock client + mockReadBytesClient := mockReadStateBytesClient(t) + + expectedReq := &proto.ReadStateBytes_Request{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + } + client.EXPECT().ReadStateBytes( + gomock.Any(), + gomock.Eq(expectedReq), + ).Return(mockReadBytesClient, nil) + + // Define what will be returned by each call to Recv + mockReadBytesClient.EXPECT().Recv().Return(&proto.ReadStateBytes_Response{ + Diagnostics: []*proto.Diagnostic{ + &proto.Diagnostic{ + Severity: proto.Diagnostic_WARNING, + Summary: "Warning from test", + Detail: "This warning is forced by the test case", + }, + }, + }, io.EOF) + + // Act + request := providers.ReadStateBytesRequest{ + TypeName: expectedReq.TypeName, + StateId: expectedReq.StateId, + } + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiags(t, resp.Diagnostics) + expectedWarn := "Warning from test: This warning is forced by the test case" + if resp.Diagnostics.ErrWithWarnings().Error() != expectedWarn { + t.Fatalf("expected warning diagnostic %q, but got: %q", expectedWarn, resp.Diagnostics.ErrWithWarnings().Error()) + } + if len(resp.Bytes) != 0 { + t.Fatalf("expected data to be omitted in error condition, but got: %q", string(resp.Bytes)) + } + }) + + t.Run("when reading data, grpc errors are surfaced via diagnostics", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Call to ReadStateBytes + // > Assert the arguments received + // > Define the returned mock client + mockClient := mockReadStateBytesClient(t) + expectedReq := &proto.ReadStateBytes_Request{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + } + client.EXPECT().ReadStateBytes( + gomock.Any(), + gomock.Eq(expectedReq), + ).Return(mockClient, nil) + + mockError := errors.New("grpc error forced in test") + mockClient.EXPECT().Recv().Return(&proto.ReadStateBytes_Response{}, mockError) + + // Act + request := providers.ReadStateBytesRequest{ + TypeName: expectedReq.TypeName, + StateId: expectedReq.StateId, + } + resp := p.ReadStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + wantErr := fmt.Sprintf("Plugin error: The plugin returned an unexpected error from plugin6.(*GRPCProvider).ReadStateBytes: %s", mockError) + if resp.Diagnostics.Err().Error() != wantErr { + t.Fatalf("expected error diagnostic %q, but got: %q", wantErr, resp.Diagnostics.Err()) + } + if len(resp.Bytes) != 0 { + t.Fatalf("expected data to be omitted in error condition, but got: %q", string(resp.Bytes)) + } + }) +} + +func TestGRPCProvider_WriteStateBytes(t *testing.T) { + t.Run("data smaller than the chunk size is sent in one write action", func(t *testing.T) { + // Less than 4MB + data := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod" + + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud" + + " exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor" + + " in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint" + + " occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") + + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Assert there will be a call to WriteStateBytes + // & make it return the mock client + mockWriteClient := mockWriteStateBytesClient(t) + client.EXPECT().WriteStateBytes( + gomock.Any(), + gomock.Any(), + ).Return(mockWriteClient, nil) + + // Spy on arguments passed to the Send method of the client + // + // We expect 1 call to Send as the total data + // is less than the chunk size + expectedReq := &proto.WriteStateBytes_RequestChunk{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + TotalLength: int64(len(data)), + Range: &proto.StateRange{ + Start: 0, + End: int64(len(data)), + }, + } + mockWriteClient.EXPECT().Send(gomock.Eq(expectedReq)).Times(1).Return(nil) + mockWriteClient.EXPECT().CloseAndRecv().Times(1).Return(&proto.WriteStateBytes_Response{}, nil) + + // Act + request := providers.WriteStateBytesRequest{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + } + resp := p.WriteStateBytes(request) + + // Assert returned values + checkDiags(t, resp.Diagnostics) + }) + + t.Run("data larger than the chunk size is sent in multiple write actions", func(t *testing.T) { + // Make a buffer that can contain 10 bytes more than the 4MB chunk size + chunkSize := 4 * 1_000_000 + dataBuff := bytes.NewBuffer(make([]byte, 0, chunkSize+10)) + dataBuffCopy := bytes.NewBuffer(make([]byte, 0, chunkSize+10)) + for i := 0; i < (chunkSize + 10); i++ { + dataBuff.WriteByte(63) // We're making 4MB + 10 bytes of question marks because why not + dataBuffCopy.WriteByte(63) // Used to make assertions + } + data := dataBuff.Bytes() + dataFirstChunk := dataBuffCopy.Next(chunkSize) // First write will have a full chunk + dataSecondChunk := dataBuffCopy.Next(chunkSize) // This will be the extra 10 bytes + + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Assert there will be a call to WriteStateBytes + // & make it return the mock client + mockWriteClient := mockWriteStateBytesClient(t) + client.EXPECT().WriteStateBytes( + gomock.Any(), + gomock.Any(), + ).Return(mockWriteClient, nil) + + // Spy on arguments passed to the Send method because data + // is written via separate chunks and separate calls to Send. + // + // We expect 2 calls to Send as the total data + // is 10 bytes larger than the chunk size + req1 := &proto.WriteStateBytes_RequestChunk{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: dataFirstChunk, + TotalLength: int64(len(data)), + Range: &proto.StateRange{ + Start: 0, + End: int64(chunkSize), + }, + } + req2 := &proto.WriteStateBytes_RequestChunk{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: dataSecondChunk, + TotalLength: int64(len(data)), + Range: &proto.StateRange{ + Start: int64(chunkSize), + End: int64(chunkSize + 10), + }, + } + mockWriteClient.EXPECT().Send(gomock.AnyOf(req1, req2)).Times(2).Return(nil) + mockWriteClient.EXPECT().CloseAndRecv().Times(1).Return(&proto.WriteStateBytes_Response{}, nil) + + // Act + request := providers.WriteStateBytesRequest{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + } + resp := p.WriteStateBytes(request) + + // Assert returned values + checkDiags(t, resp.Diagnostics) + }) + + t.Run("when writing data, grpc errors are surfaced via diagnostics", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Assert there will be a call to WriteStateBytes + // & make it return the mock client + mockWriteClient := mockWriteStateBytesClient(t) + client.EXPECT().WriteStateBytes( + gomock.Any(), + gomock.Any(), + ).Return(mockWriteClient, nil) + + mockError := errors.New("grpc error forced in test") + mockWriteClient.EXPECT().Send(gomock.Any()).Return(mockError) + + // Act + request := providers.WriteStateBytesRequest{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: []byte("helloworld"), + } + resp := p.WriteStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + wantErr := fmt.Sprintf("Plugin error: The plugin returned an unexpected error from plugin6.(*GRPCProvider).WriteStateBytes: %s", mockError) + if resp.Diagnostics.Err().Error() != wantErr { + t.Fatalf("unexpected error, wanted %q, got: %s", wantErr, resp.Diagnostics.Err()) + } + }) + + t.Run("error diagnostics from the provider when closing the connection are returned", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Assert there will be a call to WriteStateBytes + // & make it return the mock client + mockWriteClient := mockWriteStateBytesClient(t) + client.EXPECT().WriteStateBytes( + gomock.Any(), + gomock.Any(), + ).Return(mockWriteClient, nil) + + data := []byte("helloworld") + mockReq := &proto.WriteStateBytes_RequestChunk{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + TotalLength: int64(len(data)), + Range: &proto.StateRange{ + Start: 0, + End: int64(len(data)), + }, + } + mockResp := &proto.WriteStateBytes_Response{ + Diagnostics: []*proto.Diagnostic{ + { + Severity: proto.Diagnostic_ERROR, + Summary: "Error from test mock", + Detail: "This error is returned from the test mock", + }, + }, + } + mockWriteClient.EXPECT().Send(gomock.Eq(mockReq)).Times(1).Return(nil) + mockWriteClient.EXPECT().CloseAndRecv().Times(1).Return(mockResp, nil) + + // Act + request := providers.WriteStateBytesRequest{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + } + resp := p.WriteStateBytes(request) + + // Assert returned values + checkDiagsHasError(t, resp.Diagnostics) + if resp.Diagnostics.Err().Error() != "Error from test mock: This error is returned from the test mock" { + t.Fatal() + } + }) + + t.Run("warning diagnostics from the provider when closing the connection are returned", func(t *testing.T) { + client := mockProviderClient(t) + p := &GRPCProvider{ + client: client, + ctx: context.Background(), + } + + // Assert there will be a call to WriteStateBytes + // & make it return the mock client + mockWriteClient := mockWriteStateBytesClient(t) + client.EXPECT().WriteStateBytes( + gomock.Any(), + gomock.Any(), + ).Return(mockWriteClient, nil) + + data := []byte("helloworld") + mockReq := &proto.WriteStateBytes_RequestChunk{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + TotalLength: int64(len(data)), + Range: &proto.StateRange{ + Start: 0, + End: int64(len(data)), + }, + } + mockResp := &proto.WriteStateBytes_Response{ + Diagnostics: []*proto.Diagnostic{ + { + Severity: proto.Diagnostic_WARNING, + Summary: "Warning from test mock", + Detail: "This warning is returned from the test mock", + }, + }, + } + mockWriteClient.EXPECT().Send(gomock.Eq(mockReq)).Times(1).Return(nil) + mockWriteClient.EXPECT().CloseAndRecv().Times(1).Return(mockResp, nil) + + // Act + request := providers.WriteStateBytesRequest{ + TypeName: "mock_store", + StateId: backend.DefaultStateName, + Bytes: data, + } + resp := p.WriteStateBytes(request) + + // Assert returned values + checkDiags(t, resp.Diagnostics) + if resp.Diagnostics.ErrWithWarnings().Error() != "Warning from test mock: This warning is returned from the test mock" { + t.Fatal() + } + }) +} diff --git a/internal/plugin6/mock_proto/generate.go b/internal/plugin6/mock_proto/generate.go index 36cc550081ce..4d7f823b94ae 100644 --- a/internal/plugin6/mock_proto/generate.go +++ b/internal/plugin6/mock_proto/generate.go @@ -1,6 +1,6 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 -//go:generate go tool go.uber.org/mock/mockgen -destination mock.go github.com/hashicorp/terraform/internal/tfplugin6 ProviderClient,Provider_InvokeActionClient +//go:generate go tool go.uber.org/mock/mockgen -destination mock.go github.com/hashicorp/terraform/internal/tfplugin6 ProviderClient,Provider_InvokeActionClient,Provider_ReadStateBytesClient,Provider_WriteStateBytesClient package mock_tfplugin6 diff --git a/internal/plugin6/mock_proto/mock.go b/internal/plugin6/mock_proto/mock.go index efb8c225acd2..a9046ca1bba9 100644 --- a/internal/plugin6/mock_proto/mock.go +++ b/internal/plugin6/mock_proto/mock.go @@ -1,9 +1,9 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/hashicorp/terraform/internal/tfplugin6 (interfaces: ProviderClient,Provider_InvokeActionClient) +// Source: github.com/hashicorp/terraform/internal/tfplugin6 (interfaces: ProviderClient,Provider_InvokeActionClient,Provider_ReadStateBytesClient,Provider_WriteStateBytesClient) // // Generated by this command: // -// mockgen -destination mock.go github.com/hashicorp/terraform/internal/tfplugin6 ProviderClient,Provider_InvokeActionClient +// mockgen -destination mock.go github.com/hashicorp/terraform/internal/tfplugin6 ProviderClient,Provider_InvokeActionClient,Provider_ReadStateBytesClient,Provider_WriteStateBytesClient // // Package mock_tfplugin6 is a generated GoMock package. @@ -442,6 +442,26 @@ func (mr *MockProviderClientMockRecorder) ReadResource(arg0, arg1 any, arg2 ...a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadResource", reflect.TypeOf((*MockProviderClient)(nil).ReadResource), varargs...) } +// ReadStateBytes mocks base method. +func (m *MockProviderClient) ReadStateBytes(arg0 context.Context, arg1 *tfplugin6.ReadStateBytes_Request, arg2 ...grpc.CallOption) (tfplugin6.Provider_ReadStateBytesClient, error) { + m.ctrl.T.Helper() + varargs := []any{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ReadStateBytes", varargs...) + ret0, _ := ret[0].(tfplugin6.Provider_ReadStateBytesClient) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadStateBytes indicates an expected call of ReadStateBytes. +func (mr *MockProviderClientMockRecorder) ReadStateBytes(arg0, arg1 any, arg2 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadStateBytes", reflect.TypeOf((*MockProviderClient)(nil).ReadStateBytes), varargs...) +} + // RenewEphemeralResource mocks base method. func (m *MockProviderClient) RenewEphemeralResource(arg0 context.Context, arg1 *tfplugin6.RenewEphemeralResource_Request, arg2 ...grpc.CallOption) (*tfplugin6.RenewEphemeralResource_Response, error) { m.ctrl.T.Helper() @@ -662,6 +682,26 @@ func (mr *MockProviderClientMockRecorder) ValidateStateStoreConfig(arg0, arg1 an return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateStateStoreConfig", reflect.TypeOf((*MockProviderClient)(nil).ValidateStateStoreConfig), varargs...) } +// WriteStateBytes mocks base method. +func (m *MockProviderClient) WriteStateBytes(arg0 context.Context, arg1 ...grpc.CallOption) (tfplugin6.Provider_WriteStateBytesClient, error) { + m.ctrl.T.Helper() + varargs := []any{arg0} + for _, a := range arg1 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "WriteStateBytes", varargs...) + ret0, _ := ret[0].(tfplugin6.Provider_WriteStateBytesClient) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WriteStateBytes indicates an expected call of WriteStateBytes. +func (mr *MockProviderClientMockRecorder) WriteStateBytes(arg0 any, arg1 ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{arg0}, arg1...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteStateBytes", reflect.TypeOf((*MockProviderClient)(nil).WriteStateBytes), varargs...) +} + // MockProvider_InvokeActionClient is a mock of Provider_InvokeActionClient interface. type MockProvider_InvokeActionClient struct { ctrl *gomock.Controller @@ -784,3 +824,263 @@ func (mr *MockProvider_InvokeActionClientMockRecorder) Trailer() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockProvider_InvokeActionClient)(nil).Trailer)) } + +// MockProvider_ReadStateBytesClient is a mock of Provider_ReadStateBytesClient interface. +type MockProvider_ReadStateBytesClient struct { + ctrl *gomock.Controller + recorder *MockProvider_ReadStateBytesClientMockRecorder +} + +// MockProvider_ReadStateBytesClientMockRecorder is the mock recorder for MockProvider_ReadStateBytesClient. +type MockProvider_ReadStateBytesClientMockRecorder struct { + mock *MockProvider_ReadStateBytesClient +} + +// NewMockProvider_ReadStateBytesClient creates a new mock instance. +func NewMockProvider_ReadStateBytesClient(ctrl *gomock.Controller) *MockProvider_ReadStateBytesClient { + mock := &MockProvider_ReadStateBytesClient{ctrl: ctrl} + mock.recorder = &MockProvider_ReadStateBytesClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockProvider_ReadStateBytesClient) EXPECT() *MockProvider_ReadStateBytesClientMockRecorder { + return m.recorder +} + +// CloseSend mocks base method. +func (m *MockProvider_ReadStateBytesClient) CloseSend() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CloseSend") + ret0, _ := ret[0].(error) + return ret0 +} + +// CloseSend indicates an expected call of CloseSend. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) CloseSend() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).CloseSend)) +} + +// Context mocks base method. +func (m *MockProvider_ReadStateBytesClient) Context() context.Context { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(context.Context) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).Context)) +} + +// Header mocks base method. +func (m *MockProvider_ReadStateBytesClient) Header() (metadata.MD, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Header") + ret0, _ := ret[0].(metadata.MD) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Header indicates an expected call of Header. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) Header() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).Header)) +} + +// Recv mocks base method. +func (m *MockProvider_ReadStateBytesClient) Recv() (*tfplugin6.ReadStateBytes_Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Recv") + ret0, _ := ret[0].(*tfplugin6.ReadStateBytes_Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Recv indicates an expected call of Recv. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) Recv() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Recv", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).Recv)) +} + +// RecvMsg mocks base method. +func (m *MockProvider_ReadStateBytesClient) RecvMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RecvMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RecvMsg indicates an expected call of RecvMsg. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) RecvMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).RecvMsg), arg0) +} + +// SendMsg mocks base method. +func (m *MockProvider_ReadStateBytesClient) SendMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendMsg indicates an expected call of SendMsg. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) SendMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).SendMsg), arg0) +} + +// Trailer mocks base method. +func (m *MockProvider_ReadStateBytesClient) Trailer() metadata.MD { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Trailer") + ret0, _ := ret[0].(metadata.MD) + return ret0 +} + +// Trailer indicates an expected call of Trailer. +func (mr *MockProvider_ReadStateBytesClientMockRecorder) Trailer() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockProvider_ReadStateBytesClient)(nil).Trailer)) +} + +// MockProvider_WriteStateBytesClient is a mock of Provider_WriteStateBytesClient interface. +type MockProvider_WriteStateBytesClient struct { + ctrl *gomock.Controller + recorder *MockProvider_WriteStateBytesClientMockRecorder +} + +// MockProvider_WriteStateBytesClientMockRecorder is the mock recorder for MockProvider_WriteStateBytesClient. +type MockProvider_WriteStateBytesClientMockRecorder struct { + mock *MockProvider_WriteStateBytesClient +} + +// NewMockProvider_WriteStateBytesClient creates a new mock instance. +func NewMockProvider_WriteStateBytesClient(ctrl *gomock.Controller) *MockProvider_WriteStateBytesClient { + mock := &MockProvider_WriteStateBytesClient{ctrl: ctrl} + mock.recorder = &MockProvider_WriteStateBytesClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockProvider_WriteStateBytesClient) EXPECT() *MockProvider_WriteStateBytesClientMockRecorder { + return m.recorder +} + +// CloseAndRecv mocks base method. +func (m *MockProvider_WriteStateBytesClient) CloseAndRecv() (*tfplugin6.WriteStateBytes_Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CloseAndRecv") + ret0, _ := ret[0].(*tfplugin6.WriteStateBytes_Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CloseAndRecv indicates an expected call of CloseAndRecv. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) CloseAndRecv() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseAndRecv", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).CloseAndRecv)) +} + +// CloseSend mocks base method. +func (m *MockProvider_WriteStateBytesClient) CloseSend() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CloseSend") + ret0, _ := ret[0].(error) + return ret0 +} + +// CloseSend indicates an expected call of CloseSend. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) CloseSend() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CloseSend", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).CloseSend)) +} + +// Context mocks base method. +func (m *MockProvider_WriteStateBytesClient) Context() context.Context { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(context.Context) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).Context)) +} + +// Header mocks base method. +func (m *MockProvider_WriteStateBytesClient) Header() (metadata.MD, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Header") + ret0, _ := ret[0].(metadata.MD) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Header indicates an expected call of Header. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) Header() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Header", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).Header)) +} + +// RecvMsg mocks base method. +func (m *MockProvider_WriteStateBytesClient) RecvMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RecvMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RecvMsg indicates an expected call of RecvMsg. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) RecvMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RecvMsg", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).RecvMsg), arg0) +} + +// Send mocks base method. +func (m *MockProvider_WriteStateBytesClient) Send(arg0 *tfplugin6.WriteStateBytes_RequestChunk) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Send", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Send indicates an expected call of Send. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) Send(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).Send), arg0) +} + +// SendMsg mocks base method. +func (m *MockProvider_WriteStateBytesClient) SendMsg(arg0 any) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendMsg", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendMsg indicates an expected call of SendMsg. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) SendMsg(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMsg", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).SendMsg), arg0) +} + +// Trailer mocks base method. +func (m *MockProvider_WriteStateBytesClient) Trailer() metadata.MD { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Trailer") + ret0, _ := ret[0].(metadata.MD) + return ret0 +} + +// Trailer indicates an expected call of Trailer. +func (mr *MockProvider_WriteStateBytesClientMockRecorder) Trailer() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Trailer", reflect.TypeOf((*MockProvider_WriteStateBytesClient)(nil).Trailer)) +} diff --git a/internal/provider-simple-v6/provider.go b/internal/provider-simple-v6/provider.go index 10b0e5139228..639baee86e88 100644 --- a/internal/provider-simple-v6/provider.go +++ b/internal/provider-simple-v6/provider.go @@ -311,6 +311,14 @@ func (s simple) ConfigureStateStore(req providers.ConfigureStateStoreRequest) pr panic("not implemented") } +func (s simple) ReadStateBytes(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + panic("not implemented") +} + +func (s simple) WriteStateBytes(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + panic("not implemented") +} + func (s simple) GetStates(req providers.GetStatesRequest) providers.GetStatesResponse { panic("not implemented") } diff --git a/internal/provider-simple/provider.go b/internal/provider-simple/provider.go index 2cd80fe03bf3..dd55b4408278 100644 --- a/internal/provider-simple/provider.go +++ b/internal/provider-simple/provider.go @@ -271,6 +271,14 @@ func (s simple) ConfigureStateStore(req providers.ConfigureStateStoreRequest) pr panic("not implemented") } +func (s simple) ReadStateBytes(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + panic("not implemented") +} + +func (s simple) WriteStateBytes(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + panic("not implemented") +} + func (s simple) GetStates(req providers.GetStatesRequest) providers.GetStatesResponse { // provider-simple uses protocol version 5, which does not include the RPC that maps to this method panic("not implemented") diff --git a/internal/providers/mock.go b/internal/providers/mock.go index 42829b8a80e9..cba833bf2d0f 100644 --- a/internal/providers/mock.go +++ b/internal/providers/mock.go @@ -432,6 +432,14 @@ func (m *Mock) ConfigureStateStore(req ConfigureStateStoreRequest) ConfigureStat return m.Provider.ConfigureStateStore(req) } +func (m *Mock) ReadStateBytes(req ReadStateBytesRequest) ReadStateBytesResponse { + return m.Provider.ReadStateBytes(req) +} + +func (m *Mock) WriteStateBytes(req WriteStateBytesRequest) WriteStateBytesResponse { + return m.Provider.WriteStateBytes(req) +} + func (m *Mock) GetStates(req GetStatesRequest) GetStatesResponse { return m.Provider.GetStates(req) } diff --git a/internal/providers/provider.go b/internal/providers/provider.go index face2a9c154e..cbb110178b2c 100644 --- a/internal/providers/provider.go +++ b/internal/providers/provider.go @@ -118,6 +118,11 @@ type Interface interface { // ConfigureStateStore configures the state store, such as S3 connection in the context of already configured provider ConfigureStateStore(ConfigureStateStoreRequest) ConfigureStateStoreResponse + // ReadStateBytes streams byte chunks of a given state file from a state store + ReadStateBytes(ReadStateBytesRequest) ReadStateBytesResponse + // WriteStateBytes streams byte chunks of a given state file into a state store + WriteStateBytes(WriteStateBytesRequest) WriteStateBytesResponse + // GetStates returns a list of all states (i.e. CE workspaces) managed by a given state store GetStates(GetStatesRequest) GetStatesResponse // DeleteState instructs a given state store to delete a specific state (i.e. a CE workspace) @@ -850,6 +855,34 @@ type ConfigureStateStoreResponse struct { Diagnostics tfdiags.Diagnostics } +type ReadStateBytesRequest struct { + // TypeName is the name of the state store to read state from + TypeName string + // StateId is the ID of a state file to read + StateId string +} + +type ReadStateBytesResponse struct { + // Bytes represents all received bytes of the given state file + Bytes []byte + // Diagnostics contains any warnings or errors from the method call. + Diagnostics tfdiags.Diagnostics +} + +type WriteStateBytesRequest struct { + // TypeName is the name of the state store to write state to + TypeName string + // Bytes represents all bytes of the given state file to write + Bytes []byte + // StateId is the ID of a state file to write + StateId string +} + +type WriteStateBytesResponse struct { + // Diagnostics contains any warnings or errors from the method call. + Diagnostics tfdiags.Diagnostics +} + type GetStatesRequest struct { // TypeName is the name of the state store to request the list of states from TypeName string diff --git a/internal/providers/testing/provider_mock.go b/internal/providers/testing/provider_mock.go index ca5e4e1b6a6b..760ca1c3bd14 100644 --- a/internal/providers/testing/provider_mock.go +++ b/internal/providers/testing/provider_mock.go @@ -5,12 +5,15 @@ package testing import ( "fmt" + "maps" + "slices" "sync" "github.com/zclconf/go-cty/cty" ctyjson "github.com/zclconf/go-cty/cty/json" "github.com/zclconf/go-cty/cty/msgpack" + "github.com/hashicorp/hcl/v2" "github.com/hashicorp/terraform/internal/configs/hcl2shim" "github.com/hashicorp/terraform/internal/providers" ) @@ -141,6 +144,20 @@ type MockProvider struct { ConfigureStateStoreRequest providers.ConfigureStateStoreRequest ConfigureStateStoreFn func(providers.ConfigureStateStoreRequest) providers.ConfigureStateStoreResponse + ReadStateBytesCalled bool + ReadStateBytesRequest providers.ReadStateBytesRequest + ReadStateBytesFn func(providers.ReadStateBytesRequest) providers.ReadStateBytesResponse + ReadStateBytesResponse providers.ReadStateBytesResponse + + WriteStateBytesCalled bool + WriteStateBytesRequest providers.WriteStateBytesRequest + WriteStateBytesFn func(providers.WriteStateBytesRequest) providers.WriteStateBytesResponse + WriteStateBytesResponse providers.WriteStateBytesResponse + + // MockStates is an internal field that tracks which workspaces have been created in a test + // The map keys are state ids (workspaces) and the value depends on the test. + MockStates map[string]interface{} + GetStatesCalled bool GetStatesResponse *providers.GetStatesResponse GetStatesRequest providers.GetStatesRequest @@ -299,6 +316,32 @@ func (p *MockProvider) ValidateDataResourceConfig(r providers.ValidateDataResour return resp } +func (p *MockProvider) ReadStateBytes(r providers.ReadStateBytesRequest) (resp providers.ReadStateBytesResponse) { + p.Lock() + defer p.Unlock() + p.ReadStateBytesCalled = true + p.ReadStateBytesRequest = r + + if p.ReadStateBytesFn != nil { + return p.ReadStateBytesFn(r) + } + + return p.ReadStateBytesResponse +} + +func (p *MockProvider) WriteStateBytes(r providers.WriteStateBytesRequest) (resp providers.WriteStateBytesResponse) { + p.Lock() + defer p.Unlock() + p.WriteStateBytesCalled = true + p.WriteStateBytesRequest = r + + if p.WriteStateBytesFn != nil { + return p.WriteStateBytesFn(r) + } + + return p.WriteStateBytesResponse +} + func (p *MockProvider) ValidateEphemeralResourceConfig(r providers.ValidateEphemeralResourceConfigRequest) (resp providers.ValidateEphemeralResourceConfigResponse) { defer p.beginWrite()() @@ -977,11 +1020,8 @@ func (p *MockProvider) GetStates(r providers.GetStatesRequest) (resp providers.G return p.GetStatesFn(r) } - // If the mock has no further inputs, return an empty list. - // The state store should be reporting a minimum of the default workspace usually, - // but this should be achieved by querying data storage and identifying the artifact - // for that workspace, and reporting that the workspace exists. - resp.States = []string{} + // If the mock has no further inputs, return the internal states list + resp.States = slices.Sorted(maps.Keys(p.MockStates)) return resp } @@ -1008,7 +1048,15 @@ func (p *MockProvider) DeleteState(r providers.DeleteStateRequest) (resp provide return p.DeleteStateFn(r) } - // There's no logic we can include here in the absence of other fields on the mock. + if _, match := p.MockStates[r.StateId]; match { + delete(p.MockStates, r.StateId) + } else { + resp.Diagnostics.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Workspace cannot be deleted", + Detail: fmt.Sprintf("The workspace %q does not exist, so cannot be deleted", r.StateId), + }) + } // If the response contains no diagnostics then the deletion is assumed to be successful. return resp diff --git a/internal/refactoring/mock_provider.go b/internal/refactoring/mock_provider.go index 31f30935b208..b0dcff50eef9 100644 --- a/internal/refactoring/mock_provider.go +++ b/internal/refactoring/mock_provider.go @@ -130,6 +130,14 @@ func (provider *mockProvider) ConfigureStateStore(req providers.ConfigureStateSt panic("not implemented in mock") } +func (provider *mockProvider) ReadStateBytes(req providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + panic("not implemented in mock") +} + +func (provider *mockProvider) WriteStateBytes(req providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + panic("not implemented in mock") +} + func (provider *mockProvider) GetStates(req providers.GetStatesRequest) providers.GetStatesResponse { panic("not implemented in mock") } diff --git a/internal/stacks/stackruntime/internal/stackeval/stubs/errored.go b/internal/stacks/stackruntime/internal/stackeval/stubs/errored.go index 24bc2c4b9f12..e2bd82fa5cac 100644 --- a/internal/stacks/stackruntime/internal/stackeval/stubs/errored.go +++ b/internal/stacks/stackruntime/internal/stackeval/stubs/errored.go @@ -271,6 +271,34 @@ func (p *erroredProvider) ConfigureStateStore(providers.ConfigureStateStoreReque } } +// ReadStateBytes implements providers.Interface. +func (p *erroredProvider) ReadStateBytes(providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Provider configuration is invalid", + "Cannot read state managed by this state store because its associated provider configuration is invalid.", + nil, // nil attribute path means the overall configuration block + )) + return providers.ReadStateBytesResponse{ + Diagnostics: diags, + } +} + +// WriteStateBytes implements providers.Interface. +func (p *erroredProvider) WriteStateBytes(providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Provider configuration is invalid", + "Cannot write state managed by this state store because its associated provider configuration is invalid.", + nil, // nil attribute path means the overall configuration block + )) + return providers.WriteStateBytesResponse{ + Diagnostics: diags, + } +} + // GetStates implements providers.Interface. func (p *erroredProvider) GetStates(providers.GetStatesRequest) providers.GetStatesResponse { var diags tfdiags.Diagnostics diff --git a/internal/stacks/stackruntime/internal/stackeval/stubs/offline.go b/internal/stacks/stackruntime/internal/stackeval/stubs/offline.go index 2cf4a07530a0..f54c0755b750 100644 --- a/internal/stacks/stackruntime/internal/stackeval/stubs/offline.go +++ b/internal/stacks/stackruntime/internal/stackeval/stubs/offline.go @@ -288,6 +288,34 @@ func (o *offlineProvider) ConfigureStateStore(providers.ConfigureStateStoreReque } } +// ReadStateBytes implements providers.Interface. +func (o *offlineProvider) ReadStateBytes(providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Called ReadStateBytes on an unconfigured provider", + "Cannot read from state store because this provider is not configured. This is a bug in Terraform - please report it.", + nil, // nil attribute path means the overall configuration block + )) + return providers.ReadStateBytesResponse{ + Diagnostics: diags, + } +} + +// WriteStateBytes implements providers.Interface. +func (o *offlineProvider) WriteStateBytes(providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Called WriteStateBytes on an unconfigured provider", + "Cannot write to state store because this provider is not configured. This is a bug in Terraform - please report it.", + nil, // nil attribute path means the overall configuration block + )) + return providers.WriteStateBytesResponse{ + Diagnostics: diags, + } +} + // GetStates implements providers.Interface. func (o *offlineProvider) GetStates(providers.GetStatesRequest) providers.GetStatesResponse { var diags tfdiags.Diagnostics diff --git a/internal/stacks/stackruntime/internal/stackeval/stubs/unknown.go b/internal/stacks/stackruntime/internal/stackeval/stubs/unknown.go index 031575c5b7ad..9a9f77cfaeb9 100644 --- a/internal/stacks/stackruntime/internal/stackeval/stubs/unknown.go +++ b/internal/stacks/stackruntime/internal/stackeval/stubs/unknown.go @@ -336,6 +336,34 @@ func (u *unknownProvider) ConfigureStateStore(providers.ConfigureStateStoreReque } } +// ReadStateBytes implements providers.Interface. +func (u *unknownProvider) ReadStateBytes(providers.ReadStateBytesRequest) providers.ReadStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Provider configuration is unknown", + "Cannot read from this state store because its associated provider configuration is unknown.", + nil, // nil attribute path means the overall configuration block + )) + return providers.ReadStateBytesResponse{ + Diagnostics: diags, + } +} + +// WriteStateBytes implements providers.Interface. +func (u *unknownProvider) WriteStateBytes(providers.WriteStateBytesRequest) providers.WriteStateBytesResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.AttributeValue( + tfdiags.Error, + "Provider configuration is unknown", + "Cannot write to this state store because its associated provider configuration is unknown.", + nil, // nil attribute path means the overall configuration block + )) + return providers.WriteStateBytesResponse{ + Diagnostics: diags, + } +} + // GetStates implements providers.Interface. func (u *unknownProvider) GetStates(providers.GetStatesRequest) providers.GetStatesResponse { var diags tfdiags.Diagnostics diff --git a/internal/states/remote/remote_grpc.go b/internal/states/remote/remote_grpc.go index 996cda988735..448b030d9ce7 100644 --- a/internal/states/remote/remote_grpc.go +++ b/internal/states/remote/remote_grpc.go @@ -53,7 +53,23 @@ type grpcClient struct { // // Implementation of remote.Client func (g *grpcClient) Get() (*Payload, error) { - panic("not implemented yet") + // TODO - replace with method implementation added to main branch + req := providers.ReadStateBytesRequest{ + TypeName: g.typeName, + StateId: g.stateId, + } + resp := g.provider.ReadStateBytes(req) + + if len(resp.Bytes) == 0 { + // No state to return + return nil, resp.Diagnostics.Err() + } + + payload := &Payload{ + Data: resp.Bytes, + MD5: []byte("foobar"), + } + return payload, resp.Diagnostics.Err() } // Put invokes the WriteStateBytes gRPC method in the plugin protocol @@ -61,7 +77,15 @@ func (g *grpcClient) Get() (*Payload, error) { // // Implementation of remote.Client func (g *grpcClient) Put(state []byte) error { - panic("not implemented yet") + // TODO - replace with method implementation added to main branch + req := providers.WriteStateBytesRequest{ + TypeName: g.typeName, + StateId: g.stateId, + Bytes: state, + } + resp := g.provider.WriteStateBytes(req) + + return resp.Diagnostics.Err() } // Delete invokes the DeleteState gRPC method in the plugin protocol diff --git a/internal/tfplugin6/tfplugin6.pb.go b/internal/tfplugin6/tfplugin6.pb.go index 54c9ac0590e2..efa033e2f22b 100644 --- a/internal/tfplugin6/tfplugin6.pb.go +++ b/internal/tfplugin6/tfplugin6.pb.go @@ -2141,6 +2141,130 @@ func (*ConfigureStateStore) Descriptor() ([]byte, []int) { return file_tfplugin6_proto_rawDescGZIP(), []int{38} } +type ReadStateBytes struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReadStateBytes) Reset() { + *x = ReadStateBytes{} + mi := &file_tfplugin6_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReadStateBytes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadStateBytes) ProtoMessage() {} + +func (x *ReadStateBytes) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReadStateBytes.ProtoReflect.Descriptor instead. +func (*ReadStateBytes) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{39} +} + +type WriteStateBytes struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WriteStateBytes) Reset() { + *x = WriteStateBytes{} + mi := &file_tfplugin6_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WriteStateBytes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WriteStateBytes) ProtoMessage() {} + +func (x *WriteStateBytes) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WriteStateBytes.ProtoReflect.Descriptor instead. +func (*WriteStateBytes) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{40} +} + +type StateRange struct { + state protoimpl.MessageState `protogen:"open.v1"` + Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StateRange) Reset() { + *x = StateRange{} + mi := &file_tfplugin6_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StateRange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StateRange) ProtoMessage() {} + +func (x *StateRange) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[41] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StateRange.ProtoReflect.Descriptor instead. +func (*StateRange) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{41} +} + +func (x *StateRange) GetStart() int64 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *StateRange) GetEnd() int64 { + if x != nil { + return x.End + } + return 0 +} + type GetStates struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -2149,7 +2273,7 @@ type GetStates struct { func (x *GetStates) Reset() { *x = GetStates{} - mi := &file_tfplugin6_proto_msgTypes[39] + mi := &file_tfplugin6_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2161,7 +2285,7 @@ func (x *GetStates) String() string { func (*GetStates) ProtoMessage() {} func (x *GetStates) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[39] + mi := &file_tfplugin6_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2174,7 +2298,7 @@ func (x *GetStates) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStates.ProtoReflect.Descriptor instead. func (*GetStates) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{39} + return file_tfplugin6_proto_rawDescGZIP(), []int{42} } type DeleteState struct { @@ -2185,7 +2309,7 @@ type DeleteState struct { func (x *DeleteState) Reset() { *x = DeleteState{} - mi := &file_tfplugin6_proto_msgTypes[40] + mi := &file_tfplugin6_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2197,7 +2321,7 @@ func (x *DeleteState) String() string { func (*DeleteState) ProtoMessage() {} func (x *DeleteState) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[40] + mi := &file_tfplugin6_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2210,7 +2334,7 @@ func (x *DeleteState) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteState.ProtoReflect.Descriptor instead. func (*DeleteState) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{40} + return file_tfplugin6_proto_rawDescGZIP(), []int{43} } type PlanAction struct { @@ -2221,7 +2345,7 @@ type PlanAction struct { func (x *PlanAction) Reset() { *x = PlanAction{} - mi := &file_tfplugin6_proto_msgTypes[41] + mi := &file_tfplugin6_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2233,7 +2357,7 @@ func (x *PlanAction) String() string { func (*PlanAction) ProtoMessage() {} func (x *PlanAction) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[41] + mi := &file_tfplugin6_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2246,7 +2370,7 @@ func (x *PlanAction) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanAction.ProtoReflect.Descriptor instead. func (*PlanAction) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{41} + return file_tfplugin6_proto_rawDescGZIP(), []int{44} } type InvokeAction struct { @@ -2257,7 +2381,7 @@ type InvokeAction struct { func (x *InvokeAction) Reset() { *x = InvokeAction{} - mi := &file_tfplugin6_proto_msgTypes[42] + mi := &file_tfplugin6_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2269,7 +2393,7 @@ func (x *InvokeAction) String() string { func (*InvokeAction) ProtoMessage() {} func (x *InvokeAction) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[42] + mi := &file_tfplugin6_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2282,7 +2406,7 @@ func (x *InvokeAction) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeAction.ProtoReflect.Descriptor instead. func (*InvokeAction) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42} + return file_tfplugin6_proto_rawDescGZIP(), []int{45} } type ValidateActionConfig struct { @@ -2293,7 +2417,7 @@ type ValidateActionConfig struct { func (x *ValidateActionConfig) Reset() { *x = ValidateActionConfig{} - mi := &file_tfplugin6_proto_msgTypes[43] + mi := &file_tfplugin6_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2305,7 +2429,7 @@ func (x *ValidateActionConfig) String() string { func (*ValidateActionConfig) ProtoMessage() {} func (x *ValidateActionConfig) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[43] + mi := &file_tfplugin6_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2318,7 +2442,7 @@ func (x *ValidateActionConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateActionConfig.ProtoReflect.Descriptor instead. func (*ValidateActionConfig) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{43} + return file_tfplugin6_proto_rawDescGZIP(), []int{46} } type LinkedResourceConfig struct { @@ -2331,7 +2455,7 @@ type LinkedResourceConfig struct { func (x *LinkedResourceConfig) Reset() { *x = LinkedResourceConfig{} - mi := &file_tfplugin6_proto_msgTypes[44] + mi := &file_tfplugin6_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2343,7 +2467,7 @@ func (x *LinkedResourceConfig) String() string { func (*LinkedResourceConfig) ProtoMessage() {} func (x *LinkedResourceConfig) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[44] + mi := &file_tfplugin6_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2356,7 +2480,7 @@ func (x *LinkedResourceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use LinkedResourceConfig.ProtoReflect.Descriptor instead. func (*LinkedResourceConfig) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{44} + return file_tfplugin6_proto_rawDescGZIP(), []int{47} } func (x *LinkedResourceConfig) GetTypeName() string { @@ -2387,7 +2511,7 @@ type AttributePath_Step struct { func (x *AttributePath_Step) Reset() { *x = AttributePath_Step{} - mi := &file_tfplugin6_proto_msgTypes[45] + mi := &file_tfplugin6_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2399,7 +2523,7 @@ func (x *AttributePath_Step) String() string { func (*AttributePath_Step) ProtoMessage() {} func (x *AttributePath_Step) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[45] + mi := &file_tfplugin6_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2607,7 @@ type StopProvider_Request struct { func (x *StopProvider_Request) Reset() { *x = StopProvider_Request{} - mi := &file_tfplugin6_proto_msgTypes[46] + mi := &file_tfplugin6_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2495,7 +2619,7 @@ func (x *StopProvider_Request) String() string { func (*StopProvider_Request) ProtoMessage() {} func (x *StopProvider_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[46] + mi := &file_tfplugin6_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2520,7 +2644,7 @@ type StopProvider_Response struct { func (x *StopProvider_Response) Reset() { *x = StopProvider_Response{} - mi := &file_tfplugin6_proto_msgTypes[47] + mi := &file_tfplugin6_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2532,7 +2656,7 @@ func (x *StopProvider_Response) String() string { func (*StopProvider_Response) ProtoMessage() {} func (x *StopProvider_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[47] + mi := &file_tfplugin6_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2578,7 +2702,7 @@ type ResourceIdentitySchema_IdentityAttribute struct { func (x *ResourceIdentitySchema_IdentityAttribute) Reset() { *x = ResourceIdentitySchema_IdentityAttribute{} - mi := &file_tfplugin6_proto_msgTypes[49] + mi := &file_tfplugin6_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2590,7 +2714,7 @@ func (x *ResourceIdentitySchema_IdentityAttribute) String() string { func (*ResourceIdentitySchema_IdentityAttribute) ProtoMessage() {} func (x *ResourceIdentitySchema_IdentityAttribute) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[49] + mi := &file_tfplugin6_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2655,7 +2779,7 @@ type ActionSchema_LinkedResource struct { func (x *ActionSchema_LinkedResource) Reset() { *x = ActionSchema_LinkedResource{} - mi := &file_tfplugin6_proto_msgTypes[50] + mi := &file_tfplugin6_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2667,7 +2791,7 @@ func (x *ActionSchema_LinkedResource) String() string { func (*ActionSchema_LinkedResource) ProtoMessage() {} func (x *ActionSchema_LinkedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[50] + mi := &file_tfplugin6_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2707,7 +2831,7 @@ type ActionSchema_Unlinked struct { func (x *ActionSchema_Unlinked) Reset() { *x = ActionSchema_Unlinked{} - mi := &file_tfplugin6_proto_msgTypes[51] + mi := &file_tfplugin6_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2719,7 +2843,7 @@ func (x *ActionSchema_Unlinked) String() string { func (*ActionSchema_Unlinked) ProtoMessage() {} func (x *ActionSchema_Unlinked) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[51] + mi := &file_tfplugin6_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2748,7 +2872,7 @@ type ActionSchema_Lifecycle struct { func (x *ActionSchema_Lifecycle) Reset() { *x = ActionSchema_Lifecycle{} - mi := &file_tfplugin6_proto_msgTypes[52] + mi := &file_tfplugin6_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2760,7 +2884,7 @@ func (x *ActionSchema_Lifecycle) String() string { func (*ActionSchema_Lifecycle) ProtoMessage() {} func (x *ActionSchema_Lifecycle) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[52] + mi := &file_tfplugin6_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2800,7 +2924,7 @@ type ActionSchema_Linked struct { func (x *ActionSchema_Linked) Reset() { *x = ActionSchema_Linked{} - mi := &file_tfplugin6_proto_msgTypes[53] + mi := &file_tfplugin6_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2812,7 +2936,7 @@ func (x *ActionSchema_Linked) String() string { func (*ActionSchema_Linked) ProtoMessage() {} func (x *ActionSchema_Linked) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[53] + mi := &file_tfplugin6_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2849,7 +2973,7 @@ type Schema_Block struct { func (x *Schema_Block) Reset() { *x = Schema_Block{} - mi := &file_tfplugin6_proto_msgTypes[54] + mi := &file_tfplugin6_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2861,7 +2985,7 @@ func (x *Schema_Block) String() string { func (*Schema_Block) ProtoMessage() {} func (x *Schema_Block) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[54] + mi := &file_tfplugin6_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2938,7 +3062,7 @@ type Schema_Attribute struct { func (x *Schema_Attribute) Reset() { *x = Schema_Attribute{} - mi := &file_tfplugin6_proto_msgTypes[55] + mi := &file_tfplugin6_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2950,7 +3074,7 @@ func (x *Schema_Attribute) String() string { func (*Schema_Attribute) ProtoMessage() {} func (x *Schema_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[55] + mi := &file_tfplugin6_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3056,7 +3180,7 @@ type Schema_NestedBlock struct { func (x *Schema_NestedBlock) Reset() { *x = Schema_NestedBlock{} - mi := &file_tfplugin6_proto_msgTypes[56] + mi := &file_tfplugin6_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3068,7 +3192,7 @@ func (x *Schema_NestedBlock) String() string { func (*Schema_NestedBlock) ProtoMessage() {} func (x *Schema_NestedBlock) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[56] + mi := &file_tfplugin6_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3136,7 +3260,7 @@ type Schema_Object struct { func (x *Schema_Object) Reset() { *x = Schema_Object{} - mi := &file_tfplugin6_proto_msgTypes[57] + mi := &file_tfplugin6_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3148,7 +3272,7 @@ func (x *Schema_Object) String() string { func (*Schema_Object) ProtoMessage() {} func (x *Schema_Object) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[57] + mi := &file_tfplugin6_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3219,7 +3343,7 @@ type Function_Parameter struct { func (x *Function_Parameter) Reset() { *x = Function_Parameter{} - mi := &file_tfplugin6_proto_msgTypes[58] + mi := &file_tfplugin6_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3231,7 +3355,7 @@ func (x *Function_Parameter) String() string { func (*Function_Parameter) ProtoMessage() {} func (x *Function_Parameter) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[58] + mi := &file_tfplugin6_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3299,7 +3423,7 @@ type Function_Return struct { func (x *Function_Return) Reset() { *x = Function_Return{} - mi := &file_tfplugin6_proto_msgTypes[59] + mi := &file_tfplugin6_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3311,7 +3435,7 @@ func (x *Function_Return) String() string { func (*Function_Return) ProtoMessage() {} func (x *Function_Return) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[59] + mi := &file_tfplugin6_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3342,7 +3466,7 @@ type GetMetadata_Request struct { func (x *GetMetadata_Request) Reset() { *x = GetMetadata_Request{} - mi := &file_tfplugin6_proto_msgTypes[60] + mi := &file_tfplugin6_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3354,7 +3478,7 @@ func (x *GetMetadata_Request) String() string { func (*GetMetadata_Request) ProtoMessage() {} func (x *GetMetadata_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[60] + mi := &file_tfplugin6_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3388,7 +3512,7 @@ type GetMetadata_Response struct { func (x *GetMetadata_Response) Reset() { *x = GetMetadata_Response{} - mi := &file_tfplugin6_proto_msgTypes[61] + mi := &file_tfplugin6_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3400,7 +3524,7 @@ func (x *GetMetadata_Response) String() string { func (*GetMetadata_Response) ProtoMessage() {} func (x *GetMetadata_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[61] + mi := &file_tfplugin6_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3488,7 +3612,7 @@ type GetMetadata_EphemeralMetadata struct { func (x *GetMetadata_EphemeralMetadata) Reset() { *x = GetMetadata_EphemeralMetadata{} - mi := &file_tfplugin6_proto_msgTypes[62] + mi := &file_tfplugin6_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3500,7 +3624,7 @@ func (x *GetMetadata_EphemeralMetadata) String() string { func (*GetMetadata_EphemeralMetadata) ProtoMessage() {} func (x *GetMetadata_EphemeralMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[62] + mi := &file_tfplugin6_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3533,7 +3657,7 @@ type GetMetadata_FunctionMetadata struct { func (x *GetMetadata_FunctionMetadata) Reset() { *x = GetMetadata_FunctionMetadata{} - mi := &file_tfplugin6_proto_msgTypes[63] + mi := &file_tfplugin6_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3545,7 +3669,7 @@ func (x *GetMetadata_FunctionMetadata) String() string { func (*GetMetadata_FunctionMetadata) ProtoMessage() {} func (x *GetMetadata_FunctionMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[63] + mi := &file_tfplugin6_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3577,7 +3701,7 @@ type GetMetadata_DataSourceMetadata struct { func (x *GetMetadata_DataSourceMetadata) Reset() { *x = GetMetadata_DataSourceMetadata{} - mi := &file_tfplugin6_proto_msgTypes[64] + mi := &file_tfplugin6_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3589,7 +3713,7 @@ func (x *GetMetadata_DataSourceMetadata) String() string { func (*GetMetadata_DataSourceMetadata) ProtoMessage() {} func (x *GetMetadata_DataSourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[64] + mi := &file_tfplugin6_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3621,7 +3745,7 @@ type GetMetadata_ResourceMetadata struct { func (x *GetMetadata_ResourceMetadata) Reset() { *x = GetMetadata_ResourceMetadata{} - mi := &file_tfplugin6_proto_msgTypes[65] + mi := &file_tfplugin6_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3633,7 +3757,7 @@ func (x *GetMetadata_ResourceMetadata) String() string { func (*GetMetadata_ResourceMetadata) ProtoMessage() {} func (x *GetMetadata_ResourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[65] + mi := &file_tfplugin6_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3665,7 +3789,7 @@ type GetMetadata_ListResourceMetadata struct { func (x *GetMetadata_ListResourceMetadata) Reset() { *x = GetMetadata_ListResourceMetadata{} - mi := &file_tfplugin6_proto_msgTypes[66] + mi := &file_tfplugin6_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3677,7 +3801,7 @@ func (x *GetMetadata_ListResourceMetadata) String() string { func (*GetMetadata_ListResourceMetadata) ProtoMessage() {} func (x *GetMetadata_ListResourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[66] + mi := &file_tfplugin6_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3709,7 +3833,7 @@ type GetMetadata_StateStoreMetadata struct { func (x *GetMetadata_StateStoreMetadata) Reset() { *x = GetMetadata_StateStoreMetadata{} - mi := &file_tfplugin6_proto_msgTypes[67] + mi := &file_tfplugin6_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3721,7 +3845,7 @@ func (x *GetMetadata_StateStoreMetadata) String() string { func (*GetMetadata_StateStoreMetadata) ProtoMessage() {} func (x *GetMetadata_StateStoreMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[67] + mi := &file_tfplugin6_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3753,7 +3877,7 @@ type GetMetadata_ActionMetadata struct { func (x *GetMetadata_ActionMetadata) Reset() { *x = GetMetadata_ActionMetadata{} - mi := &file_tfplugin6_proto_msgTypes[68] + mi := &file_tfplugin6_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3765,7 +3889,7 @@ func (x *GetMetadata_ActionMetadata) String() string { func (*GetMetadata_ActionMetadata) ProtoMessage() {} func (x *GetMetadata_ActionMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[68] + mi := &file_tfplugin6_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3796,7 +3920,7 @@ type GetProviderSchema_Request struct { func (x *GetProviderSchema_Request) Reset() { *x = GetProviderSchema_Request{} - mi := &file_tfplugin6_proto_msgTypes[69] + mi := &file_tfplugin6_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3808,7 +3932,7 @@ func (x *GetProviderSchema_Request) String() string { func (*GetProviderSchema_Request) ProtoMessage() {} func (x *GetProviderSchema_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[69] + mi := &file_tfplugin6_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3843,7 +3967,7 @@ type GetProviderSchema_Response struct { func (x *GetProviderSchema_Response) Reset() { *x = GetProviderSchema_Response{} - mi := &file_tfplugin6_proto_msgTypes[70] + mi := &file_tfplugin6_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3855,7 +3979,7 @@ func (x *GetProviderSchema_Response) String() string { func (*GetProviderSchema_Response) ProtoMessage() {} func (x *GetProviderSchema_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[70] + mi := &file_tfplugin6_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3957,7 +4081,7 @@ type ValidateProviderConfig_Request struct { func (x *ValidateProviderConfig_Request) Reset() { *x = ValidateProviderConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[78] + mi := &file_tfplugin6_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3969,7 +4093,7 @@ func (x *ValidateProviderConfig_Request) String() string { func (*ValidateProviderConfig_Request) ProtoMessage() {} func (x *ValidateProviderConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[78] + mi := &file_tfplugin6_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4001,7 +4125,7 @@ type ValidateProviderConfig_Response struct { func (x *ValidateProviderConfig_Response) Reset() { *x = ValidateProviderConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[79] + mi := &file_tfplugin6_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4013,7 +4137,7 @@ func (x *ValidateProviderConfig_Response) String() string { func (*ValidateProviderConfig_Response) ProtoMessage() {} func (x *ValidateProviderConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[79] + mi := &file_tfplugin6_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4062,7 +4186,7 @@ type UpgradeResourceState_Request struct { func (x *UpgradeResourceState_Request) Reset() { *x = UpgradeResourceState_Request{} - mi := &file_tfplugin6_proto_msgTypes[80] + mi := &file_tfplugin6_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4074,7 +4198,7 @@ func (x *UpgradeResourceState_Request) String() string { func (*UpgradeResourceState_Request) ProtoMessage() {} func (x *UpgradeResourceState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[80] + mi := &file_tfplugin6_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4127,7 +4251,7 @@ type UpgradeResourceState_Response struct { func (x *UpgradeResourceState_Response) Reset() { *x = UpgradeResourceState_Response{} - mi := &file_tfplugin6_proto_msgTypes[81] + mi := &file_tfplugin6_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4139,7 +4263,7 @@ func (x *UpgradeResourceState_Response) String() string { func (*UpgradeResourceState_Response) ProtoMessage() {} func (x *UpgradeResourceState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[81] + mi := &file_tfplugin6_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4177,7 +4301,7 @@ type GetResourceIdentitySchemas_Request struct { func (x *GetResourceIdentitySchemas_Request) Reset() { *x = GetResourceIdentitySchemas_Request{} - mi := &file_tfplugin6_proto_msgTypes[82] + mi := &file_tfplugin6_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4189,7 +4313,7 @@ func (x *GetResourceIdentitySchemas_Request) String() string { func (*GetResourceIdentitySchemas_Request) ProtoMessage() {} func (x *GetResourceIdentitySchemas_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[82] + mi := &file_tfplugin6_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4217,7 +4341,7 @@ type GetResourceIdentitySchemas_Response struct { func (x *GetResourceIdentitySchemas_Response) Reset() { *x = GetResourceIdentitySchemas_Response{} - mi := &file_tfplugin6_proto_msgTypes[83] + mi := &file_tfplugin6_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4229,7 +4353,7 @@ func (x *GetResourceIdentitySchemas_Response) String() string { func (*GetResourceIdentitySchemas_Response) ProtoMessage() {} func (x *GetResourceIdentitySchemas_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[83] + mi := &file_tfplugin6_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4276,7 +4400,7 @@ type UpgradeResourceIdentity_Request struct { func (x *UpgradeResourceIdentity_Request) Reset() { *x = UpgradeResourceIdentity_Request{} - mi := &file_tfplugin6_proto_msgTypes[85] + mi := &file_tfplugin6_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4288,7 +4412,7 @@ func (x *UpgradeResourceIdentity_Request) String() string { func (*UpgradeResourceIdentity_Request) ProtoMessage() {} func (x *UpgradeResourceIdentity_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[85] + mi := &file_tfplugin6_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4337,7 +4461,7 @@ type UpgradeResourceIdentity_Response struct { func (x *UpgradeResourceIdentity_Response) Reset() { *x = UpgradeResourceIdentity_Response{} - mi := &file_tfplugin6_proto_msgTypes[86] + mi := &file_tfplugin6_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4349,7 +4473,7 @@ func (x *UpgradeResourceIdentity_Response) String() string { func (*UpgradeResourceIdentity_Response) ProtoMessage() {} func (x *UpgradeResourceIdentity_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[86] + mi := &file_tfplugin6_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4390,7 +4514,7 @@ type ValidateResourceConfig_Request struct { func (x *ValidateResourceConfig_Request) Reset() { *x = ValidateResourceConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[87] + mi := &file_tfplugin6_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4402,7 +4526,7 @@ func (x *ValidateResourceConfig_Request) String() string { func (*ValidateResourceConfig_Request) ProtoMessage() {} func (x *ValidateResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[87] + mi := &file_tfplugin6_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4448,7 +4572,7 @@ type ValidateResourceConfig_Response struct { func (x *ValidateResourceConfig_Response) Reset() { *x = ValidateResourceConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[88] + mi := &file_tfplugin6_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4460,7 +4584,7 @@ func (x *ValidateResourceConfig_Response) String() string { func (*ValidateResourceConfig_Response) ProtoMessage() {} func (x *ValidateResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[88] + mi := &file_tfplugin6_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4493,7 +4617,7 @@ type ValidateDataResourceConfig_Request struct { func (x *ValidateDataResourceConfig_Request) Reset() { *x = ValidateDataResourceConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[89] + mi := &file_tfplugin6_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4505,7 +4629,7 @@ func (x *ValidateDataResourceConfig_Request) String() string { func (*ValidateDataResourceConfig_Request) ProtoMessage() {} func (x *ValidateDataResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[89] + mi := &file_tfplugin6_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4544,7 +4668,7 @@ type ValidateDataResourceConfig_Response struct { func (x *ValidateDataResourceConfig_Response) Reset() { *x = ValidateDataResourceConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[90] + mi := &file_tfplugin6_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4556,7 +4680,7 @@ func (x *ValidateDataResourceConfig_Response) String() string { func (*ValidateDataResourceConfig_Response) ProtoMessage() {} func (x *ValidateDataResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[90] + mi := &file_tfplugin6_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4589,7 +4713,7 @@ type ValidateEphemeralResourceConfig_Request struct { func (x *ValidateEphemeralResourceConfig_Request) Reset() { *x = ValidateEphemeralResourceConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[91] + mi := &file_tfplugin6_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4601,7 +4725,7 @@ func (x *ValidateEphemeralResourceConfig_Request) String() string { func (*ValidateEphemeralResourceConfig_Request) ProtoMessage() {} func (x *ValidateEphemeralResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[91] + mi := &file_tfplugin6_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4640,7 +4764,7 @@ type ValidateEphemeralResourceConfig_Response struct { func (x *ValidateEphemeralResourceConfig_Response) Reset() { *x = ValidateEphemeralResourceConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[92] + mi := &file_tfplugin6_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4652,7 +4776,7 @@ func (x *ValidateEphemeralResourceConfig_Response) String() string { func (*ValidateEphemeralResourceConfig_Response) ProtoMessage() {} func (x *ValidateEphemeralResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[92] + mi := &file_tfplugin6_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4686,7 +4810,7 @@ type ConfigureProvider_Request struct { func (x *ConfigureProvider_Request) Reset() { *x = ConfigureProvider_Request{} - mi := &file_tfplugin6_proto_msgTypes[93] + mi := &file_tfplugin6_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4698,7 +4822,7 @@ func (x *ConfigureProvider_Request) String() string { func (*ConfigureProvider_Request) ProtoMessage() {} func (x *ConfigureProvider_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[93] + mi := &file_tfplugin6_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4744,7 +4868,7 @@ type ConfigureProvider_Response struct { func (x *ConfigureProvider_Response) Reset() { *x = ConfigureProvider_Response{} - mi := &file_tfplugin6_proto_msgTypes[94] + mi := &file_tfplugin6_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4756,7 +4880,7 @@ func (x *ConfigureProvider_Response) String() string { func (*ConfigureProvider_Response) ProtoMessage() {} func (x *ConfigureProvider_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[94] + mi := &file_tfplugin6_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4801,7 +4925,7 @@ type ReadResource_Request struct { func (x *ReadResource_Request) Reset() { *x = ReadResource_Request{} - mi := &file_tfplugin6_proto_msgTypes[95] + mi := &file_tfplugin6_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4813,7 +4937,7 @@ func (x *ReadResource_Request) String() string { func (*ReadResource_Request) ProtoMessage() {} func (x *ReadResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[95] + mi := &file_tfplugin6_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4886,7 +5010,7 @@ type ReadResource_Response struct { func (x *ReadResource_Response) Reset() { *x = ReadResource_Response{} - mi := &file_tfplugin6_proto_msgTypes[96] + mi := &file_tfplugin6_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4898,7 +5022,7 @@ func (x *ReadResource_Response) String() string { func (*ReadResource_Response) ProtoMessage() {} func (x *ReadResource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[96] + mi := &file_tfplugin6_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4965,7 +5089,7 @@ type PlanResourceChange_Request struct { func (x *PlanResourceChange_Request) Reset() { *x = PlanResourceChange_Request{} - mi := &file_tfplugin6_proto_msgTypes[97] + mi := &file_tfplugin6_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4977,7 +5101,7 @@ func (x *PlanResourceChange_Request) String() string { func (*PlanResourceChange_Request) ProtoMessage() {} func (x *PlanResourceChange_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[97] + mi := &file_tfplugin6_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5077,7 +5201,7 @@ type PlanResourceChange_Response struct { func (x *PlanResourceChange_Response) Reset() { *x = PlanResourceChange_Response{} - mi := &file_tfplugin6_proto_msgTypes[98] + mi := &file_tfplugin6_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5089,7 +5213,7 @@ func (x *PlanResourceChange_Response) String() string { func (*PlanResourceChange_Response) ProtoMessage() {} func (x *PlanResourceChange_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[98] + mi := &file_tfplugin6_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5169,7 +5293,7 @@ type ApplyResourceChange_Request struct { func (x *ApplyResourceChange_Request) Reset() { *x = ApplyResourceChange_Request{} - mi := &file_tfplugin6_proto_msgTypes[99] + mi := &file_tfplugin6_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5181,7 +5305,7 @@ func (x *ApplyResourceChange_Request) String() string { func (*ApplyResourceChange_Request) ProtoMessage() {} func (x *ApplyResourceChange_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[99] + mi := &file_tfplugin6_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5270,7 +5394,7 @@ type ApplyResourceChange_Response struct { func (x *ApplyResourceChange_Response) Reset() { *x = ApplyResourceChange_Response{} - mi := &file_tfplugin6_proto_msgTypes[100] + mi := &file_tfplugin6_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5282,7 +5406,7 @@ func (x *ApplyResourceChange_Response) String() string { func (*ApplyResourceChange_Response) ProtoMessage() {} func (x *ApplyResourceChange_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[100] + mi := &file_tfplugin6_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5345,7 +5469,7 @@ type ImportResourceState_Request struct { func (x *ImportResourceState_Request) Reset() { *x = ImportResourceState_Request{} - mi := &file_tfplugin6_proto_msgTypes[101] + mi := &file_tfplugin6_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5357,7 +5481,7 @@ func (x *ImportResourceState_Request) String() string { func (*ImportResourceState_Request) ProtoMessage() {} func (x *ImportResourceState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[101] + mi := &file_tfplugin6_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5413,7 +5537,7 @@ type ImportResourceState_ImportedResource struct { func (x *ImportResourceState_ImportedResource) Reset() { *x = ImportResourceState_ImportedResource{} - mi := &file_tfplugin6_proto_msgTypes[102] + mi := &file_tfplugin6_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5425,7 +5549,7 @@ func (x *ImportResourceState_ImportedResource) String() string { func (*ImportResourceState_ImportedResource) ProtoMessage() {} func (x *ImportResourceState_ImportedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[102] + mi := &file_tfplugin6_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5482,7 +5606,7 @@ type ImportResourceState_Response struct { func (x *ImportResourceState_Response) Reset() { *x = ImportResourceState_Response{} - mi := &file_tfplugin6_proto_msgTypes[103] + mi := &file_tfplugin6_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5494,7 +5618,7 @@ func (x *ImportResourceState_Response) String() string { func (*ImportResourceState_Response) ProtoMessage() {} func (x *ImportResourceState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[103] + mi := &file_tfplugin6_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5561,7 +5685,7 @@ type MoveResourceState_Request struct { func (x *MoveResourceState_Request) Reset() { *x = MoveResourceState_Request{} - mi := &file_tfplugin6_proto_msgTypes[104] + mi := &file_tfplugin6_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5573,7 +5697,7 @@ func (x *MoveResourceState_Request) String() string { func (*MoveResourceState_Request) ProtoMessage() {} func (x *MoveResourceState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[104] + mi := &file_tfplugin6_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5660,7 +5784,7 @@ type MoveResourceState_Response struct { func (x *MoveResourceState_Response) Reset() { *x = MoveResourceState_Response{} - mi := &file_tfplugin6_proto_msgTypes[105] + mi := &file_tfplugin6_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5672,7 +5796,7 @@ func (x *MoveResourceState_Response) String() string { func (*MoveResourceState_Response) ProtoMessage() {} func (x *MoveResourceState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[105] + mi := &file_tfplugin6_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5728,7 +5852,7 @@ type ReadDataSource_Request struct { func (x *ReadDataSource_Request) Reset() { *x = ReadDataSource_Request{} - mi := &file_tfplugin6_proto_msgTypes[106] + mi := &file_tfplugin6_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5740,7 +5864,7 @@ func (x *ReadDataSource_Request) String() string { func (*ReadDataSource_Request) ProtoMessage() {} func (x *ReadDataSource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[106] + mi := &file_tfplugin6_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5797,7 +5921,7 @@ type ReadDataSource_Response struct { func (x *ReadDataSource_Response) Reset() { *x = ReadDataSource_Response{} - mi := &file_tfplugin6_proto_msgTypes[107] + mi := &file_tfplugin6_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5809,7 +5933,7 @@ func (x *ReadDataSource_Response) String() string { func (*ReadDataSource_Response) ProtoMessage() {} func (x *ReadDataSource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[107] + mi := &file_tfplugin6_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5857,7 +5981,7 @@ type OpenEphemeralResource_Request struct { func (x *OpenEphemeralResource_Request) Reset() { *x = OpenEphemeralResource_Request{} - mi := &file_tfplugin6_proto_msgTypes[108] + mi := &file_tfplugin6_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5869,7 +5993,7 @@ func (x *OpenEphemeralResource_Request) String() string { func (*OpenEphemeralResource_Request) ProtoMessage() {} func (x *OpenEphemeralResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[108] + mi := &file_tfplugin6_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5919,7 +6043,7 @@ type OpenEphemeralResource_Response struct { func (x *OpenEphemeralResource_Response) Reset() { *x = OpenEphemeralResource_Response{} - mi := &file_tfplugin6_proto_msgTypes[109] + mi := &file_tfplugin6_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5931,7 +6055,7 @@ func (x *OpenEphemeralResource_Response) String() string { func (*OpenEphemeralResource_Response) ProtoMessage() {} func (x *OpenEphemeralResource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[109] + mi := &file_tfplugin6_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5992,7 +6116,7 @@ type RenewEphemeralResource_Request struct { func (x *RenewEphemeralResource_Request) Reset() { *x = RenewEphemeralResource_Request{} - mi := &file_tfplugin6_proto_msgTypes[110] + mi := &file_tfplugin6_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6004,7 +6128,7 @@ func (x *RenewEphemeralResource_Request) String() string { func (*RenewEphemeralResource_Request) ProtoMessage() {} func (x *RenewEphemeralResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[110] + mi := &file_tfplugin6_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6045,7 +6169,7 @@ type RenewEphemeralResource_Response struct { func (x *RenewEphemeralResource_Response) Reset() { *x = RenewEphemeralResource_Response{} - mi := &file_tfplugin6_proto_msgTypes[111] + mi := &file_tfplugin6_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6057,7 +6181,7 @@ func (x *RenewEphemeralResource_Response) String() string { func (*RenewEphemeralResource_Response) ProtoMessage() {} func (x *RenewEphemeralResource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[111] + mi := &file_tfplugin6_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6104,7 +6228,7 @@ type CloseEphemeralResource_Request struct { func (x *CloseEphemeralResource_Request) Reset() { *x = CloseEphemeralResource_Request{} - mi := &file_tfplugin6_proto_msgTypes[112] + mi := &file_tfplugin6_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6116,7 +6240,7 @@ func (x *CloseEphemeralResource_Request) String() string { func (*CloseEphemeralResource_Request) ProtoMessage() {} func (x *CloseEphemeralResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[112] + mi := &file_tfplugin6_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6155,7 +6279,7 @@ type CloseEphemeralResource_Response struct { func (x *CloseEphemeralResource_Response) Reset() { *x = CloseEphemeralResource_Response{} - mi := &file_tfplugin6_proto_msgTypes[113] + mi := &file_tfplugin6_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6167,7 +6291,7 @@ func (x *CloseEphemeralResource_Response) String() string { func (*CloseEphemeralResource_Response) ProtoMessage() {} func (x *CloseEphemeralResource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[113] + mi := &file_tfplugin6_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6198,7 +6322,7 @@ type GetFunctions_Request struct { func (x *GetFunctions_Request) Reset() { *x = GetFunctions_Request{} - mi := &file_tfplugin6_proto_msgTypes[114] + mi := &file_tfplugin6_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6210,7 +6334,7 @@ func (x *GetFunctions_Request) String() string { func (*GetFunctions_Request) ProtoMessage() {} func (x *GetFunctions_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[114] + mi := &file_tfplugin6_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6238,7 +6362,7 @@ type GetFunctions_Response struct { func (x *GetFunctions_Response) Reset() { *x = GetFunctions_Response{} - mi := &file_tfplugin6_proto_msgTypes[115] + mi := &file_tfplugin6_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6250,7 +6374,7 @@ func (x *GetFunctions_Response) String() string { func (*GetFunctions_Response) ProtoMessage() {} func (x *GetFunctions_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[115] + mi := &file_tfplugin6_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6290,7 +6414,7 @@ type CallFunction_Request struct { func (x *CallFunction_Request) Reset() { *x = CallFunction_Request{} - mi := &file_tfplugin6_proto_msgTypes[117] + mi := &file_tfplugin6_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6302,7 +6426,7 @@ func (x *CallFunction_Request) String() string { func (*CallFunction_Request) ProtoMessage() {} func (x *CallFunction_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[117] + mi := &file_tfplugin6_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6342,7 +6466,7 @@ type CallFunction_Response struct { func (x *CallFunction_Response) Reset() { *x = CallFunction_Response{} - mi := &file_tfplugin6_proto_msgTypes[118] + mi := &file_tfplugin6_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6354,7 +6478,7 @@ func (x *CallFunction_Response) String() string { func (*CallFunction_Response) ProtoMessage() {} func (x *CallFunction_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[118] + mi := &file_tfplugin6_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6402,7 +6526,7 @@ type ListResource_Request struct { func (x *ListResource_Request) Reset() { *x = ListResource_Request{} - mi := &file_tfplugin6_proto_msgTypes[119] + mi := &file_tfplugin6_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6414,7 +6538,7 @@ func (x *ListResource_Request) String() string { func (*ListResource_Request) ProtoMessage() {} func (x *ListResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[119] + mi := &file_tfplugin6_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6474,7 +6598,7 @@ type ListResource_Event struct { func (x *ListResource_Event) Reset() { *x = ListResource_Event{} - mi := &file_tfplugin6_proto_msgTypes[120] + mi := &file_tfplugin6_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6486,7 +6610,7 @@ func (x *ListResource_Event) String() string { func (*ListResource_Event) ProtoMessage() {} func (x *ListResource_Event) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[120] + mi := &file_tfplugin6_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6542,7 +6666,7 @@ type ValidateListResourceConfig_Request struct { func (x *ValidateListResourceConfig_Request) Reset() { *x = ValidateListResourceConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[121] + mi := &file_tfplugin6_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6554,7 +6678,7 @@ func (x *ValidateListResourceConfig_Request) String() string { func (*ValidateListResourceConfig_Request) ProtoMessage() {} func (x *ValidateListResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[121] + mi := &file_tfplugin6_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6607,7 +6731,7 @@ type ValidateListResourceConfig_Response struct { func (x *ValidateListResourceConfig_Response) Reset() { *x = ValidateListResourceConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[122] + mi := &file_tfplugin6_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6619,7 +6743,7 @@ func (x *ValidateListResourceConfig_Response) String() string { func (*ValidateListResourceConfig_Response) ProtoMessage() {} func (x *ValidateListResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[122] + mi := &file_tfplugin6_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6645,26 +6769,218 @@ func (x *ValidateListResourceConfig_Response) GetDiagnostics() []*Diagnostic { type ValidateStateStore_Request struct { state protoimpl.MessageState `protogen:"open.v1"` 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"` + Config *DynamicValue `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ValidateStateStore_Request) Reset() { + *x = ValidateStateStore_Request{} + mi := &file_tfplugin6_proto_msgTypes[126] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ValidateStateStore_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateStateStore_Request) ProtoMessage() {} + +func (x *ValidateStateStore_Request) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[126] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateStateStore_Request.ProtoReflect.Descriptor instead. +func (*ValidateStateStore_Request) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{37, 0} +} + +func (x *ValidateStateStore_Request) GetTypeName() string { + if x != nil { + return x.TypeName + } + return "" +} + +func (x *ValidateStateStore_Request) GetConfig() *DynamicValue { + if x != nil { + return x.Config + } + return nil +} + +type ValidateStateStore_Response struct { + state protoimpl.MessageState `protogen:"open.v1"` + Diagnostics []*Diagnostic `protobuf:"bytes,1,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ValidateStateStore_Response) Reset() { + *x = ValidateStateStore_Response{} + mi := &file_tfplugin6_proto_msgTypes[127] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ValidateStateStore_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ValidateStateStore_Response) ProtoMessage() {} + +func (x *ValidateStateStore_Response) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[127] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ValidateStateStore_Response.ProtoReflect.Descriptor instead. +func (*ValidateStateStore_Response) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{37, 1} +} + +func (x *ValidateStateStore_Response) GetDiagnostics() []*Diagnostic { + if x != nil { + return x.Diagnostics + } + return nil +} + +type ConfigureStateStore_Request struct { + state protoimpl.MessageState `protogen:"open.v1"` + 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"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigureStateStore_Request) Reset() { + *x = ConfigureStateStore_Request{} + mi := &file_tfplugin6_proto_msgTypes[128] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigureStateStore_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigureStateStore_Request) ProtoMessage() {} + +func (x *ConfigureStateStore_Request) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[128] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigureStateStore_Request.ProtoReflect.Descriptor instead. +func (*ConfigureStateStore_Request) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{38, 0} +} + +func (x *ConfigureStateStore_Request) GetTypeName() string { + if x != nil { + return x.TypeName + } + return "" +} + +func (x *ConfigureStateStore_Request) GetConfig() *DynamicValue { + if x != nil { + return x.Config + } + return nil +} + +type ConfigureStateStore_Response struct { + state protoimpl.MessageState `protogen:"open.v1"` + Diagnostics []*Diagnostic `protobuf:"bytes,1,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConfigureStateStore_Response) Reset() { + *x = ConfigureStateStore_Response{} + mi := &file_tfplugin6_proto_msgTypes[129] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfigureStateStore_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigureStateStore_Response) ProtoMessage() {} + +func (x *ConfigureStateStore_Response) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[129] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfigureStateStore_Response.ProtoReflect.Descriptor instead. +func (*ConfigureStateStore_Response) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{38, 1} +} + +func (x *ConfigureStateStore_Response) GetDiagnostics() []*Diagnostic { + if x != nil { + return x.Diagnostics + } + return nil +} + +type ReadStateBytes_Request struct { + state protoimpl.MessageState `protogen:"open.v1"` + TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` + StateId string `protobuf:"bytes,2,opt,name=state_id,json=stateId,proto3" json:"state_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ValidateStateStore_Request) Reset() { - *x = ValidateStateStore_Request{} - mi := &file_tfplugin6_proto_msgTypes[123] +func (x *ReadStateBytes_Request) Reset() { + *x = ReadStateBytes_Request{} + mi := &file_tfplugin6_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ValidateStateStore_Request) String() string { +func (x *ReadStateBytes_Request) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ValidateStateStore_Request) ProtoMessage() {} +func (*ReadStateBytes_Request) ProtoMessage() {} -func (x *ValidateStateStore_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[123] +func (x *ReadStateBytes_Request) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6675,47 +6991,50 @@ func (x *ValidateStateStore_Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ValidateStateStore_Request.ProtoReflect.Descriptor instead. -func (*ValidateStateStore_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{37, 0} +// Deprecated: Use ReadStateBytes_Request.ProtoReflect.Descriptor instead. +func (*ReadStateBytes_Request) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{39, 0} } -func (x *ValidateStateStore_Request) GetTypeName() string { +func (x *ReadStateBytes_Request) GetTypeName() string { if x != nil { return x.TypeName } return "" } -func (x *ValidateStateStore_Request) GetConfig() *DynamicValue { +func (x *ReadStateBytes_Request) GetStateId() string { if x != nil { - return x.Config + return x.StateId } - return nil + return "" } -type ValidateStateStore_Response struct { +type ReadStateBytes_Response struct { state protoimpl.MessageState `protogen:"open.v1"` - Diagnostics []*Diagnostic `protobuf:"bytes,1,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + Bytes []byte `protobuf:"bytes,1,opt,name=bytes,proto3" json:"bytes,omitempty"` + TotalLength int64 `protobuf:"varint,2,opt,name=total_length,json=totalLength,proto3" json:"total_length,omitempty"` + Range *StateRange `protobuf:"bytes,3,opt,name=range,proto3" json:"range,omitempty"` + Diagnostics []*Diagnostic `protobuf:"bytes,4,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ValidateStateStore_Response) Reset() { - *x = ValidateStateStore_Response{} - mi := &file_tfplugin6_proto_msgTypes[124] +func (x *ReadStateBytes_Response) Reset() { + *x = ReadStateBytes_Response{} + mi := &file_tfplugin6_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ValidateStateStore_Response) String() string { +func (x *ReadStateBytes_Response) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ValidateStateStore_Response) ProtoMessage() {} +func (*ReadStateBytes_Response) ProtoMessage() {} -func (x *ValidateStateStore_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[124] +func (x *ReadStateBytes_Response) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6726,41 +7045,66 @@ func (x *ValidateStateStore_Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ValidateStateStore_Response.ProtoReflect.Descriptor instead. -func (*ValidateStateStore_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{37, 1} +// Deprecated: Use ReadStateBytes_Response.ProtoReflect.Descriptor instead. +func (*ReadStateBytes_Response) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{39, 1} } -func (x *ValidateStateStore_Response) GetDiagnostics() []*Diagnostic { +func (x *ReadStateBytes_Response) GetBytes() []byte { + if x != nil { + return x.Bytes + } + return nil +} + +func (x *ReadStateBytes_Response) GetTotalLength() int64 { + if x != nil { + return x.TotalLength + } + return 0 +} + +func (x *ReadStateBytes_Response) GetRange() *StateRange { + if x != nil { + return x.Range + } + return nil +} + +func (x *ReadStateBytes_Response) GetDiagnostics() []*Diagnostic { if x != nil { return x.Diagnostics } return nil } -type ConfigureStateStore_Request struct { - state protoimpl.MessageState `protogen:"open.v1"` - 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"` +type WriteStateBytes_RequestChunk struct { + state protoimpl.MessageState `protogen:"open.v1"` + // TODO: Can we decouple this outside of the stream? + TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` + StateId string `protobuf:"bytes,3,opt,name=state_id,json=stateId,proto3" json:"state_id,omitempty"` + Bytes []byte `protobuf:"bytes,2,opt,name=bytes,proto3" json:"bytes,omitempty"` + TotalLength int64 `protobuf:"varint,4,opt,name=total_length,json=totalLength,proto3" json:"total_length,omitempty"` + Range *StateRange `protobuf:"bytes,5,opt,name=range,proto3" json:"range,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ConfigureStateStore_Request) Reset() { - *x = ConfigureStateStore_Request{} - mi := &file_tfplugin6_proto_msgTypes[125] +func (x *WriteStateBytes_RequestChunk) Reset() { + *x = WriteStateBytes_RequestChunk{} + mi := &file_tfplugin6_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ConfigureStateStore_Request) String() string { +func (x *WriteStateBytes_RequestChunk) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ConfigureStateStore_Request) ProtoMessage() {} +func (*WriteStateBytes_RequestChunk) ProtoMessage() {} -func (x *ConfigureStateStore_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[125] +func (x *WriteStateBytes_RequestChunk) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6771,47 +7115,68 @@ func (x *ConfigureStateStore_Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ConfigureStateStore_Request.ProtoReflect.Descriptor instead. -func (*ConfigureStateStore_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{38, 0} +// Deprecated: Use WriteStateBytes_RequestChunk.ProtoReflect.Descriptor instead. +func (*WriteStateBytes_RequestChunk) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{40, 0} } -func (x *ConfigureStateStore_Request) GetTypeName() string { +func (x *WriteStateBytes_RequestChunk) GetTypeName() string { if x != nil { return x.TypeName } return "" } -func (x *ConfigureStateStore_Request) GetConfig() *DynamicValue { +func (x *WriteStateBytes_RequestChunk) GetStateId() string { if x != nil { - return x.Config + return x.StateId + } + return "" +} + +func (x *WriteStateBytes_RequestChunk) GetBytes() []byte { + if x != nil { + return x.Bytes } return nil } -type ConfigureStateStore_Response struct { +func (x *WriteStateBytes_RequestChunk) GetTotalLength() int64 { + if x != nil { + return x.TotalLength + } + return 0 +} + +func (x *WriteStateBytes_RequestChunk) GetRange() *StateRange { + if x != nil { + return x.Range + } + return nil +} + +type WriteStateBytes_Response struct { state protoimpl.MessageState `protogen:"open.v1"` Diagnostics []*Diagnostic `protobuf:"bytes,1,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *ConfigureStateStore_Response) Reset() { - *x = ConfigureStateStore_Response{} - mi := &file_tfplugin6_proto_msgTypes[126] +func (x *WriteStateBytes_Response) Reset() { + *x = WriteStateBytes_Response{} + mi := &file_tfplugin6_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *ConfigureStateStore_Response) String() string { +func (x *WriteStateBytes_Response) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ConfigureStateStore_Response) ProtoMessage() {} +func (*WriteStateBytes_Response) ProtoMessage() {} -func (x *ConfigureStateStore_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[126] +func (x *WriteStateBytes_Response) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6822,12 +7187,12 @@ func (x *ConfigureStateStore_Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ConfigureStateStore_Response.ProtoReflect.Descriptor instead. -func (*ConfigureStateStore_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{38, 1} +// Deprecated: Use WriteStateBytes_Response.ProtoReflect.Descriptor instead. +func (*WriteStateBytes_Response) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{40, 1} } -func (x *ConfigureStateStore_Response) GetDiagnostics() []*Diagnostic { +func (x *WriteStateBytes_Response) GetDiagnostics() []*Diagnostic { if x != nil { return x.Diagnostics } @@ -6843,7 +7208,7 @@ type GetStates_Request struct { func (x *GetStates_Request) Reset() { *x = GetStates_Request{} - mi := &file_tfplugin6_proto_msgTypes[127] + mi := &file_tfplugin6_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6855,7 +7220,7 @@ func (x *GetStates_Request) String() string { func (*GetStates_Request) ProtoMessage() {} func (x *GetStates_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[127] + mi := &file_tfplugin6_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6868,7 +7233,7 @@ func (x *GetStates_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStates_Request.ProtoReflect.Descriptor instead. func (*GetStates_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{39, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{42, 0} } func (x *GetStates_Request) GetTypeName() string { @@ -6888,7 +7253,7 @@ type GetStates_Response struct { func (x *GetStates_Response) Reset() { *x = GetStates_Response{} - mi := &file_tfplugin6_proto_msgTypes[128] + mi := &file_tfplugin6_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6900,7 +7265,7 @@ func (x *GetStates_Response) String() string { func (*GetStates_Response) ProtoMessage() {} func (x *GetStates_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[128] + mi := &file_tfplugin6_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6913,7 +7278,7 @@ func (x *GetStates_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStates_Response.ProtoReflect.Descriptor instead. func (*GetStates_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{39, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{42, 1} } func (x *GetStates_Response) GetStateId() []string { @@ -6940,7 +7305,7 @@ type DeleteState_Request struct { func (x *DeleteState_Request) Reset() { *x = DeleteState_Request{} - mi := &file_tfplugin6_proto_msgTypes[129] + mi := &file_tfplugin6_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6952,7 +7317,7 @@ func (x *DeleteState_Request) String() string { func (*DeleteState_Request) ProtoMessage() {} func (x *DeleteState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[129] + mi := &file_tfplugin6_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6965,7 +7330,7 @@ func (x *DeleteState_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteState_Request.ProtoReflect.Descriptor instead. func (*DeleteState_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{40, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{43, 0} } func (x *DeleteState_Request) GetTypeName() string { @@ -6991,7 +7356,7 @@ type DeleteState_Response struct { func (x *DeleteState_Response) Reset() { *x = DeleteState_Response{} - mi := &file_tfplugin6_proto_msgTypes[130] + mi := &file_tfplugin6_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7003,7 +7368,7 @@ func (x *DeleteState_Response) String() string { func (*DeleteState_Response) ProtoMessage() {} func (x *DeleteState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[130] + mi := &file_tfplugin6_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7016,7 +7381,7 @@ func (x *DeleteState_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteState_Response.ProtoReflect.Descriptor instead. func (*DeleteState_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{40, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{43, 1} } func (x *DeleteState_Response) GetDiagnostics() []*Diagnostic { @@ -7041,7 +7406,7 @@ type PlanAction_Request struct { func (x *PlanAction_Request) Reset() { *x = PlanAction_Request{} - mi := &file_tfplugin6_proto_msgTypes[131] + mi := &file_tfplugin6_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7053,7 +7418,7 @@ func (x *PlanAction_Request) String() string { func (*PlanAction_Request) ProtoMessage() {} func (x *PlanAction_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[131] + mi := &file_tfplugin6_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7066,7 +7431,7 @@ func (x *PlanAction_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanAction_Request.ProtoReflect.Descriptor instead. func (*PlanAction_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{41, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{44, 0} } func (x *PlanAction_Request) GetActionType() string { @@ -7110,7 +7475,7 @@ type PlanAction_Response struct { func (x *PlanAction_Response) Reset() { *x = PlanAction_Response{} - mi := &file_tfplugin6_proto_msgTypes[132] + mi := &file_tfplugin6_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7122,7 +7487,7 @@ func (x *PlanAction_Response) String() string { func (*PlanAction_Response) ProtoMessage() {} func (x *PlanAction_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[132] + mi := &file_tfplugin6_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7135,7 +7500,7 @@ func (x *PlanAction_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanAction_Response.ProtoReflect.Descriptor instead. func (*PlanAction_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{41, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{44, 1} } func (x *PlanAction_Response) GetLinkedResources() []*PlanAction_Response_LinkedResource { @@ -7174,7 +7539,7 @@ type PlanAction_Request_LinkedResource struct { func (x *PlanAction_Request_LinkedResource) Reset() { *x = PlanAction_Request_LinkedResource{} - mi := &file_tfplugin6_proto_msgTypes[133] + mi := &file_tfplugin6_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7186,7 +7551,7 @@ func (x *PlanAction_Request_LinkedResource) String() string { func (*PlanAction_Request_LinkedResource) ProtoMessage() {} func (x *PlanAction_Request_LinkedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[133] + mi := &file_tfplugin6_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7199,7 +7564,7 @@ func (x *PlanAction_Request_LinkedResource) ProtoReflect() protoreflect.Message // Deprecated: Use PlanAction_Request_LinkedResource.ProtoReflect.Descriptor instead. func (*PlanAction_Request_LinkedResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{41, 0, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{44, 0, 0} } func (x *PlanAction_Request_LinkedResource) GetPriorState() *DynamicValue { @@ -7240,7 +7605,7 @@ type PlanAction_Response_LinkedResource struct { func (x *PlanAction_Response_LinkedResource) Reset() { *x = PlanAction_Response_LinkedResource{} - mi := &file_tfplugin6_proto_msgTypes[134] + mi := &file_tfplugin6_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7252,7 +7617,7 @@ func (x *PlanAction_Response_LinkedResource) String() string { func (*PlanAction_Response_LinkedResource) ProtoMessage() {} func (x *PlanAction_Response_LinkedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[134] + mi := &file_tfplugin6_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7265,7 +7630,7 @@ func (x *PlanAction_Response_LinkedResource) ProtoReflect() protoreflect.Message // Deprecated: Use PlanAction_Response_LinkedResource.ProtoReflect.Descriptor instead. func (*PlanAction_Response_LinkedResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{41, 1, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{44, 1, 0} } func (x *PlanAction_Response_LinkedResource) GetPlannedState() *DynamicValue { @@ -7297,7 +7662,7 @@ type InvokeAction_Request struct { func (x *InvokeAction_Request) Reset() { *x = InvokeAction_Request{} - mi := &file_tfplugin6_proto_msgTypes[135] + mi := &file_tfplugin6_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7309,7 +7674,7 @@ func (x *InvokeAction_Request) String() string { func (*InvokeAction_Request) ProtoMessage() {} func (x *InvokeAction_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[135] + mi := &file_tfplugin6_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7322,7 +7687,7 @@ func (x *InvokeAction_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeAction_Request.ProtoReflect.Descriptor instead. func (*InvokeAction_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 0} } func (x *InvokeAction_Request) GetActionType() string { @@ -7366,7 +7731,7 @@ type InvokeAction_Event struct { func (x *InvokeAction_Event) Reset() { *x = InvokeAction_Event{} - mi := &file_tfplugin6_proto_msgTypes[136] + mi := &file_tfplugin6_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7378,7 +7743,7 @@ func (x *InvokeAction_Event) String() string { func (*InvokeAction_Event) ProtoMessage() {} func (x *InvokeAction_Event) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[136] + mi := &file_tfplugin6_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7391,7 +7756,7 @@ func (x *InvokeAction_Event) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeAction_Event.ProtoReflect.Descriptor instead. func (*InvokeAction_Event) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 1} } func (x *InvokeAction_Event) GetType() isInvokeAction_Event_Type { @@ -7449,7 +7814,7 @@ type InvokeAction_Request_LinkedResource struct { func (x *InvokeAction_Request_LinkedResource) Reset() { *x = InvokeAction_Request_LinkedResource{} - mi := &file_tfplugin6_proto_msgTypes[137] + mi := &file_tfplugin6_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7461,7 +7826,7 @@ func (x *InvokeAction_Request_LinkedResource) String() string { func (*InvokeAction_Request_LinkedResource) ProtoMessage() {} func (x *InvokeAction_Request_LinkedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[137] + mi := &file_tfplugin6_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7474,7 +7839,7 @@ func (x *InvokeAction_Request_LinkedResource) ProtoReflect() protoreflect.Messag // Deprecated: Use InvokeAction_Request_LinkedResource.ProtoReflect.Descriptor instead. func (*InvokeAction_Request_LinkedResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 0, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 0, 0} } func (x *InvokeAction_Request_LinkedResource) GetPriorState() *DynamicValue { @@ -7515,7 +7880,7 @@ type InvokeAction_Event_Progress struct { func (x *InvokeAction_Event_Progress) Reset() { *x = InvokeAction_Event_Progress{} - mi := &file_tfplugin6_proto_msgTypes[138] + mi := &file_tfplugin6_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7527,7 +7892,7 @@ func (x *InvokeAction_Event_Progress) String() string { func (*InvokeAction_Event_Progress) ProtoMessage() {} func (x *InvokeAction_Event_Progress) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[138] + mi := &file_tfplugin6_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7540,7 +7905,7 @@ func (x *InvokeAction_Event_Progress) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeAction_Event_Progress.ProtoReflect.Descriptor instead. func (*InvokeAction_Event_Progress) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 1, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 1, 0} } func (x *InvokeAction_Event_Progress) GetMessage() string { @@ -7561,7 +7926,7 @@ type InvokeAction_Event_Completed struct { func (x *InvokeAction_Event_Completed) Reset() { *x = InvokeAction_Event_Completed{} - mi := &file_tfplugin6_proto_msgTypes[139] + mi := &file_tfplugin6_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7573,7 +7938,7 @@ func (x *InvokeAction_Event_Completed) String() string { func (*InvokeAction_Event_Completed) ProtoMessage() {} func (x *InvokeAction_Event_Completed) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[139] + mi := &file_tfplugin6_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7586,7 +7951,7 @@ func (x *InvokeAction_Event_Completed) ProtoReflect() protoreflect.Message { // Deprecated: Use InvokeAction_Event_Completed.ProtoReflect.Descriptor instead. func (*InvokeAction_Event_Completed) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 1, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 1, 1} } func (x *InvokeAction_Event_Completed) GetLinkedResources() []*InvokeAction_Event_Completed_LinkedResource { @@ -7615,7 +7980,7 @@ type InvokeAction_Event_Completed_LinkedResource struct { func (x *InvokeAction_Event_Completed_LinkedResource) Reset() { *x = InvokeAction_Event_Completed_LinkedResource{} - mi := &file_tfplugin6_proto_msgTypes[140] + mi := &file_tfplugin6_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7627,7 +7992,7 @@ func (x *InvokeAction_Event_Completed_LinkedResource) String() string { func (*InvokeAction_Event_Completed_LinkedResource) ProtoMessage() {} func (x *InvokeAction_Event_Completed_LinkedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[140] + mi := &file_tfplugin6_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7640,7 +8005,7 @@ func (x *InvokeAction_Event_Completed_LinkedResource) ProtoReflect() protoreflec // Deprecated: Use InvokeAction_Event_Completed_LinkedResource.ProtoReflect.Descriptor instead. func (*InvokeAction_Event_Completed_LinkedResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{42, 1, 1, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{45, 1, 1, 0} } func (x *InvokeAction_Event_Completed_LinkedResource) GetNewState() *DynamicValue { @@ -7675,7 +8040,7 @@ type ValidateActionConfig_Request struct { func (x *ValidateActionConfig_Request) Reset() { *x = ValidateActionConfig_Request{} - mi := &file_tfplugin6_proto_msgTypes[141] + mi := &file_tfplugin6_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7687,7 +8052,7 @@ func (x *ValidateActionConfig_Request) String() string { func (*ValidateActionConfig_Request) ProtoMessage() {} func (x *ValidateActionConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[141] + mi := &file_tfplugin6_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7700,7 +8065,7 @@ func (x *ValidateActionConfig_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateActionConfig_Request.ProtoReflect.Descriptor instead. func (*ValidateActionConfig_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{43, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{46, 0} } func (x *ValidateActionConfig_Request) GetTypeName() string { @@ -7733,7 +8098,7 @@ type ValidateActionConfig_Response struct { func (x *ValidateActionConfig_Response) Reset() { *x = ValidateActionConfig_Response{} - mi := &file_tfplugin6_proto_msgTypes[142] + mi := &file_tfplugin6_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7745,7 +8110,7 @@ func (x *ValidateActionConfig_Response) String() string { func (*ValidateActionConfig_Response) ProtoMessage() {} func (x *ValidateActionConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[142] + mi := &file_tfplugin6_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7758,7 +8123,7 @@ func (x *ValidateActionConfig_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateActionConfig_Response.ProtoReflect.Descriptor instead. func (*ValidateActionConfig_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{43, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{46, 1} } func (x *ValidateActionConfig_Response) GetDiagnostics() []*Diagnostic { @@ -8223,7 +8588,29 @@ const file_tfplugin6_proto_rawDesc = "" + "\ttype_name\x18\x01 \x01(\tR\btypeName\x12/\n" + "\x06config\x18\x02 \x01(\v2\x17.tfplugin6.DynamicValueR\x06config\x1aC\n" + "\bResponse\x127\n" + - "\vdiagnostics\x18\x01 \x03(\v2\x15.tfplugin6.DiagnosticR\vdiagnostics\"\x93\x01\n" + + "\vdiagnostics\x18\x01 \x03(\v2\x15.tfplugin6.DiagnosticR\vdiagnostics\"\xff\x01\n" + + "\x0eReadStateBytes\x1aA\n" + + "\aRequest\x12\x1b\n" + + "\ttype_name\x18\x01 \x01(\tR\btypeName\x12\x19\n" + + "\bstate_id\x18\x02 \x01(\tR\astateId\x1a\xa9\x01\n" + + "\bResponse\x12\x14\n" + + "\x05bytes\x18\x01 \x01(\fR\x05bytes\x12!\n" + + "\ftotal_length\x18\x02 \x01(\x03R\vtotalLength\x12+\n" + + "\x05range\x18\x03 \x01(\v2\x15.tfplugin6.StateRangeR\x05range\x127\n" + + "\vdiagnostics\x18\x04 \x03(\v2\x15.tfplugin6.DiagnosticR\vdiagnostics\"\x85\x02\n" + + "\x0fWriteStateBytes\x1a\xac\x01\n" + + "\fRequestChunk\x12\x1b\n" + + "\ttype_name\x18\x01 \x01(\tR\btypeName\x12\x19\n" + + "\bstate_id\x18\x03 \x01(\tR\astateId\x12\x14\n" + + "\x05bytes\x18\x02 \x01(\fR\x05bytes\x12!\n" + + "\ftotal_length\x18\x04 \x01(\x03R\vtotalLength\x12+\n" + + "\x05range\x18\x05 \x01(\v2\x15.tfplugin6.StateRangeR\x05range\x1aC\n" + + "\bResponse\x127\n" + + "\vdiagnostics\x18\x01 \x03(\v2\x15.tfplugin6.DiagnosticR\vdiagnostics\"4\n" + + "\n" + + "StateRange\x12\x14\n" + + "\x05start\x18\x01 \x01(\x03R\x05start\x12\x10\n" + + "\x03end\x18\x02 \x01(\x03R\x03end\"\x93\x01\n" + "\tGetStates\x1a&\n" + "\aRequest\x12\x1b\n" + "\ttype_name\x18\x01 \x01(\tR\btypeName\x1a^\n" + @@ -8296,7 +8683,7 @@ const file_tfplugin6_proto_rawDesc = "" + "\n" + "StringKind\x12\t\n" + "\x05PLAIN\x10\x00\x12\f\n" + - "\bMARKDOWN\x10\x012\xb8\x18\n" + + "\bMARKDOWN\x10\x012\xf6\x19\n" + "\bProvider\x12N\n" + "\vGetMetadata\x12\x1e.tfplugin6.GetMetadata.Request\x1a\x1f.tfplugin6.GetMetadata.Response\x12`\n" + "\x11GetProviderSchema\x12$.tfplugin6.GetProviderSchema.Request\x1a%.tfplugin6.GetProviderSchema.Response\x12o\n" + @@ -8322,7 +8709,9 @@ const file_tfplugin6_proto_rawDesc = "" + "\fGetFunctions\x12\x1f.tfplugin6.GetFunctions.Request\x1a .tfplugin6.GetFunctions.Response\x12Q\n" + "\fCallFunction\x12\x1f.tfplugin6.CallFunction.Request\x1a .tfplugin6.CallFunction.Response\x12i\n" + "\x18ValidateStateStoreConfig\x12%.tfplugin6.ValidateStateStore.Request\x1a&.tfplugin6.ValidateStateStore.Response\x12f\n" + - "\x13ConfigureStateStore\x12&.tfplugin6.ConfigureStateStore.Request\x1a'.tfplugin6.ConfigureStateStore.Response\x12H\n" + + "\x13ConfigureStateStore\x12&.tfplugin6.ConfigureStateStore.Request\x1a'.tfplugin6.ConfigureStateStore.Response\x12Y\n" + + "\x0eReadStateBytes\x12!.tfplugin6.ReadStateBytes.Request\x1a\".tfplugin6.ReadStateBytes.Response0\x01\x12a\n" + + "\x0fWriteStateBytes\x12'.tfplugin6.WriteStateBytes.RequestChunk\x1a#.tfplugin6.WriteStateBytes.Response(\x01\x12H\n" + "\tGetStates\x12\x1c.tfplugin6.GetStates.Request\x1a\x1d.tfplugin6.GetStates.Response\x12N\n" + "\vDeleteState\x12\x1e.tfplugin6.DeleteState.Request\x1a\x1f.tfplugin6.DeleteState.Response\x12K\n" + "\n" + @@ -8344,7 +8733,7 @@ func file_tfplugin6_proto_rawDescGZIP() []byte { } var file_tfplugin6_proto_enumTypes = make([]protoimpl.EnumInfo, 6) -var file_tfplugin6_proto_msgTypes = make([]protoimpl.MessageInfo, 143) +var file_tfplugin6_proto_msgTypes = make([]protoimpl.MessageInfo, 150) var file_tfplugin6_proto_goTypes = []any{ (StringKind)(0), // 0: tfplugin6.StringKind (Diagnostic_Severity)(0), // 1: tfplugin6.Diagnostic.Severity @@ -8391,160 +8780,167 @@ var file_tfplugin6_proto_goTypes = []any{ (*ValidateListResourceConfig)(nil), // 42: tfplugin6.ValidateListResourceConfig (*ValidateStateStore)(nil), // 43: tfplugin6.ValidateStateStore (*ConfigureStateStore)(nil), // 44: tfplugin6.ConfigureStateStore - (*GetStates)(nil), // 45: tfplugin6.GetStates - (*DeleteState)(nil), // 46: tfplugin6.DeleteState - (*PlanAction)(nil), // 47: tfplugin6.PlanAction - (*InvokeAction)(nil), // 48: tfplugin6.InvokeAction - (*ValidateActionConfig)(nil), // 49: tfplugin6.ValidateActionConfig - (*LinkedResourceConfig)(nil), // 50: tfplugin6.LinkedResourceConfig - (*AttributePath_Step)(nil), // 51: tfplugin6.AttributePath.Step - (*StopProvider_Request)(nil), // 52: tfplugin6.StopProvider.Request - (*StopProvider_Response)(nil), // 53: tfplugin6.StopProvider.Response - nil, // 54: tfplugin6.RawState.FlatmapEntry - (*ResourceIdentitySchema_IdentityAttribute)(nil), // 55: tfplugin6.ResourceIdentitySchema.IdentityAttribute - (*ActionSchema_LinkedResource)(nil), // 56: tfplugin6.ActionSchema.LinkedResource - (*ActionSchema_Unlinked)(nil), // 57: tfplugin6.ActionSchema.Unlinked - (*ActionSchema_Lifecycle)(nil), // 58: tfplugin6.ActionSchema.Lifecycle - (*ActionSchema_Linked)(nil), // 59: tfplugin6.ActionSchema.Linked - (*Schema_Block)(nil), // 60: tfplugin6.Schema.Block - (*Schema_Attribute)(nil), // 61: tfplugin6.Schema.Attribute - (*Schema_NestedBlock)(nil), // 62: tfplugin6.Schema.NestedBlock - (*Schema_Object)(nil), // 63: tfplugin6.Schema.Object - (*Function_Parameter)(nil), // 64: tfplugin6.Function.Parameter - (*Function_Return)(nil), // 65: tfplugin6.Function.Return - (*GetMetadata_Request)(nil), // 66: tfplugin6.GetMetadata.Request - (*GetMetadata_Response)(nil), // 67: tfplugin6.GetMetadata.Response - (*GetMetadata_EphemeralMetadata)(nil), // 68: tfplugin6.GetMetadata.EphemeralMetadata - (*GetMetadata_FunctionMetadata)(nil), // 69: tfplugin6.GetMetadata.FunctionMetadata - (*GetMetadata_DataSourceMetadata)(nil), // 70: tfplugin6.GetMetadata.DataSourceMetadata - (*GetMetadata_ResourceMetadata)(nil), // 71: tfplugin6.GetMetadata.ResourceMetadata - (*GetMetadata_ListResourceMetadata)(nil), // 72: tfplugin6.GetMetadata.ListResourceMetadata - (*GetMetadata_StateStoreMetadata)(nil), // 73: tfplugin6.GetMetadata.StateStoreMetadata - (*GetMetadata_ActionMetadata)(nil), // 74: tfplugin6.GetMetadata.ActionMetadata - (*GetProviderSchema_Request)(nil), // 75: tfplugin6.GetProviderSchema.Request - (*GetProviderSchema_Response)(nil), // 76: tfplugin6.GetProviderSchema.Response - nil, // 77: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry - nil, // 78: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry - nil, // 79: tfplugin6.GetProviderSchema.Response.FunctionsEntry - nil, // 80: tfplugin6.GetProviderSchema.Response.EphemeralResourceSchemasEntry - nil, // 81: tfplugin6.GetProviderSchema.Response.ListResourceSchemasEntry - nil, // 82: tfplugin6.GetProviderSchema.Response.StateStoreSchemasEntry - nil, // 83: tfplugin6.GetProviderSchema.Response.ActionSchemasEntry - (*ValidateProviderConfig_Request)(nil), // 84: tfplugin6.ValidateProviderConfig.Request - (*ValidateProviderConfig_Response)(nil), // 85: tfplugin6.ValidateProviderConfig.Response - (*UpgradeResourceState_Request)(nil), // 86: tfplugin6.UpgradeResourceState.Request - (*UpgradeResourceState_Response)(nil), // 87: tfplugin6.UpgradeResourceState.Response - (*GetResourceIdentitySchemas_Request)(nil), // 88: tfplugin6.GetResourceIdentitySchemas.Request - (*GetResourceIdentitySchemas_Response)(nil), // 89: tfplugin6.GetResourceIdentitySchemas.Response - nil, // 90: tfplugin6.GetResourceIdentitySchemas.Response.IdentitySchemasEntry - (*UpgradeResourceIdentity_Request)(nil), // 91: tfplugin6.UpgradeResourceIdentity.Request - (*UpgradeResourceIdentity_Response)(nil), // 92: tfplugin6.UpgradeResourceIdentity.Response - (*ValidateResourceConfig_Request)(nil), // 93: tfplugin6.ValidateResourceConfig.Request - (*ValidateResourceConfig_Response)(nil), // 94: tfplugin6.ValidateResourceConfig.Response - (*ValidateDataResourceConfig_Request)(nil), // 95: tfplugin6.ValidateDataResourceConfig.Request - (*ValidateDataResourceConfig_Response)(nil), // 96: tfplugin6.ValidateDataResourceConfig.Response - (*ValidateEphemeralResourceConfig_Request)(nil), // 97: tfplugin6.ValidateEphemeralResourceConfig.Request - (*ValidateEphemeralResourceConfig_Response)(nil), // 98: tfplugin6.ValidateEphemeralResourceConfig.Response - (*ConfigureProvider_Request)(nil), // 99: tfplugin6.ConfigureProvider.Request - (*ConfigureProvider_Response)(nil), // 100: tfplugin6.ConfigureProvider.Response - (*ReadResource_Request)(nil), // 101: tfplugin6.ReadResource.Request - (*ReadResource_Response)(nil), // 102: tfplugin6.ReadResource.Response - (*PlanResourceChange_Request)(nil), // 103: tfplugin6.PlanResourceChange.Request - (*PlanResourceChange_Response)(nil), // 104: tfplugin6.PlanResourceChange.Response - (*ApplyResourceChange_Request)(nil), // 105: tfplugin6.ApplyResourceChange.Request - (*ApplyResourceChange_Response)(nil), // 106: tfplugin6.ApplyResourceChange.Response - (*ImportResourceState_Request)(nil), // 107: tfplugin6.ImportResourceState.Request - (*ImportResourceState_ImportedResource)(nil), // 108: tfplugin6.ImportResourceState.ImportedResource - (*ImportResourceState_Response)(nil), // 109: tfplugin6.ImportResourceState.Response - (*MoveResourceState_Request)(nil), // 110: tfplugin6.MoveResourceState.Request - (*MoveResourceState_Response)(nil), // 111: tfplugin6.MoveResourceState.Response - (*ReadDataSource_Request)(nil), // 112: tfplugin6.ReadDataSource.Request - (*ReadDataSource_Response)(nil), // 113: tfplugin6.ReadDataSource.Response - (*OpenEphemeralResource_Request)(nil), // 114: tfplugin6.OpenEphemeralResource.Request - (*OpenEphemeralResource_Response)(nil), // 115: tfplugin6.OpenEphemeralResource.Response - (*RenewEphemeralResource_Request)(nil), // 116: tfplugin6.RenewEphemeralResource.Request - (*RenewEphemeralResource_Response)(nil), // 117: tfplugin6.RenewEphemeralResource.Response - (*CloseEphemeralResource_Request)(nil), // 118: tfplugin6.CloseEphemeralResource.Request - (*CloseEphemeralResource_Response)(nil), // 119: tfplugin6.CloseEphemeralResource.Response - (*GetFunctions_Request)(nil), // 120: tfplugin6.GetFunctions.Request - (*GetFunctions_Response)(nil), // 121: tfplugin6.GetFunctions.Response - nil, // 122: tfplugin6.GetFunctions.Response.FunctionsEntry - (*CallFunction_Request)(nil), // 123: tfplugin6.CallFunction.Request - (*CallFunction_Response)(nil), // 124: tfplugin6.CallFunction.Response - (*ListResource_Request)(nil), // 125: tfplugin6.ListResource.Request - (*ListResource_Event)(nil), // 126: tfplugin6.ListResource.Event - (*ValidateListResourceConfig_Request)(nil), // 127: tfplugin6.ValidateListResourceConfig.Request - (*ValidateListResourceConfig_Response)(nil), // 128: tfplugin6.ValidateListResourceConfig.Response - (*ValidateStateStore_Request)(nil), // 129: tfplugin6.ValidateStateStore.Request - (*ValidateStateStore_Response)(nil), // 130: tfplugin6.ValidateStateStore.Response - (*ConfigureStateStore_Request)(nil), // 131: tfplugin6.ConfigureStateStore.Request - (*ConfigureStateStore_Response)(nil), // 132: tfplugin6.ConfigureStateStore.Response - (*GetStates_Request)(nil), // 133: tfplugin6.GetStates.Request - (*GetStates_Response)(nil), // 134: tfplugin6.GetStates.Response - (*DeleteState_Request)(nil), // 135: tfplugin6.DeleteState.Request - (*DeleteState_Response)(nil), // 136: tfplugin6.DeleteState.Response - (*PlanAction_Request)(nil), // 137: tfplugin6.PlanAction.Request - (*PlanAction_Response)(nil), // 138: tfplugin6.PlanAction.Response - (*PlanAction_Request_LinkedResource)(nil), // 139: tfplugin6.PlanAction.Request.LinkedResource - (*PlanAction_Response_LinkedResource)(nil), // 140: tfplugin6.PlanAction.Response.LinkedResource - (*InvokeAction_Request)(nil), // 141: tfplugin6.InvokeAction.Request - (*InvokeAction_Event)(nil), // 142: tfplugin6.InvokeAction.Event - (*InvokeAction_Request_LinkedResource)(nil), // 143: tfplugin6.InvokeAction.Request.LinkedResource - (*InvokeAction_Event_Progress)(nil), // 144: tfplugin6.InvokeAction.Event.Progress - (*InvokeAction_Event_Completed)(nil), // 145: tfplugin6.InvokeAction.Event.Completed - (*InvokeAction_Event_Completed_LinkedResource)(nil), // 146: tfplugin6.InvokeAction.Event.Completed.LinkedResource - (*ValidateActionConfig_Request)(nil), // 147: tfplugin6.ValidateActionConfig.Request - (*ValidateActionConfig_Response)(nil), // 148: tfplugin6.ValidateActionConfig.Response - (*timestamppb.Timestamp)(nil), // 149: google.protobuf.Timestamp + (*ReadStateBytes)(nil), // 45: tfplugin6.ReadStateBytes + (*WriteStateBytes)(nil), // 46: tfplugin6.WriteStateBytes + (*StateRange)(nil), // 47: tfplugin6.StateRange + (*GetStates)(nil), // 48: tfplugin6.GetStates + (*DeleteState)(nil), // 49: tfplugin6.DeleteState + (*PlanAction)(nil), // 50: tfplugin6.PlanAction + (*InvokeAction)(nil), // 51: tfplugin6.InvokeAction + (*ValidateActionConfig)(nil), // 52: tfplugin6.ValidateActionConfig + (*LinkedResourceConfig)(nil), // 53: tfplugin6.LinkedResourceConfig + (*AttributePath_Step)(nil), // 54: tfplugin6.AttributePath.Step + (*StopProvider_Request)(nil), // 55: tfplugin6.StopProvider.Request + (*StopProvider_Response)(nil), // 56: tfplugin6.StopProvider.Response + nil, // 57: tfplugin6.RawState.FlatmapEntry + (*ResourceIdentitySchema_IdentityAttribute)(nil), // 58: tfplugin6.ResourceIdentitySchema.IdentityAttribute + (*ActionSchema_LinkedResource)(nil), // 59: tfplugin6.ActionSchema.LinkedResource + (*ActionSchema_Unlinked)(nil), // 60: tfplugin6.ActionSchema.Unlinked + (*ActionSchema_Lifecycle)(nil), // 61: tfplugin6.ActionSchema.Lifecycle + (*ActionSchema_Linked)(nil), // 62: tfplugin6.ActionSchema.Linked + (*Schema_Block)(nil), // 63: tfplugin6.Schema.Block + (*Schema_Attribute)(nil), // 64: tfplugin6.Schema.Attribute + (*Schema_NestedBlock)(nil), // 65: tfplugin6.Schema.NestedBlock + (*Schema_Object)(nil), // 66: tfplugin6.Schema.Object + (*Function_Parameter)(nil), // 67: tfplugin6.Function.Parameter + (*Function_Return)(nil), // 68: tfplugin6.Function.Return + (*GetMetadata_Request)(nil), // 69: tfplugin6.GetMetadata.Request + (*GetMetadata_Response)(nil), // 70: tfplugin6.GetMetadata.Response + (*GetMetadata_EphemeralMetadata)(nil), // 71: tfplugin6.GetMetadata.EphemeralMetadata + (*GetMetadata_FunctionMetadata)(nil), // 72: tfplugin6.GetMetadata.FunctionMetadata + (*GetMetadata_DataSourceMetadata)(nil), // 73: tfplugin6.GetMetadata.DataSourceMetadata + (*GetMetadata_ResourceMetadata)(nil), // 74: tfplugin6.GetMetadata.ResourceMetadata + (*GetMetadata_ListResourceMetadata)(nil), // 75: tfplugin6.GetMetadata.ListResourceMetadata + (*GetMetadata_StateStoreMetadata)(nil), // 76: tfplugin6.GetMetadata.StateStoreMetadata + (*GetMetadata_ActionMetadata)(nil), // 77: tfplugin6.GetMetadata.ActionMetadata + (*GetProviderSchema_Request)(nil), // 78: tfplugin6.GetProviderSchema.Request + (*GetProviderSchema_Response)(nil), // 79: tfplugin6.GetProviderSchema.Response + nil, // 80: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry + nil, // 81: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry + nil, // 82: tfplugin6.GetProviderSchema.Response.FunctionsEntry + nil, // 83: tfplugin6.GetProviderSchema.Response.EphemeralResourceSchemasEntry + nil, // 84: tfplugin6.GetProviderSchema.Response.ListResourceSchemasEntry + nil, // 85: tfplugin6.GetProviderSchema.Response.StateStoreSchemasEntry + nil, // 86: tfplugin6.GetProviderSchema.Response.ActionSchemasEntry + (*ValidateProviderConfig_Request)(nil), // 87: tfplugin6.ValidateProviderConfig.Request + (*ValidateProviderConfig_Response)(nil), // 88: tfplugin6.ValidateProviderConfig.Response + (*UpgradeResourceState_Request)(nil), // 89: tfplugin6.UpgradeResourceState.Request + (*UpgradeResourceState_Response)(nil), // 90: tfplugin6.UpgradeResourceState.Response + (*GetResourceIdentitySchemas_Request)(nil), // 91: tfplugin6.GetResourceIdentitySchemas.Request + (*GetResourceIdentitySchemas_Response)(nil), // 92: tfplugin6.GetResourceIdentitySchemas.Response + nil, // 93: tfplugin6.GetResourceIdentitySchemas.Response.IdentitySchemasEntry + (*UpgradeResourceIdentity_Request)(nil), // 94: tfplugin6.UpgradeResourceIdentity.Request + (*UpgradeResourceIdentity_Response)(nil), // 95: tfplugin6.UpgradeResourceIdentity.Response + (*ValidateResourceConfig_Request)(nil), // 96: tfplugin6.ValidateResourceConfig.Request + (*ValidateResourceConfig_Response)(nil), // 97: tfplugin6.ValidateResourceConfig.Response + (*ValidateDataResourceConfig_Request)(nil), // 98: tfplugin6.ValidateDataResourceConfig.Request + (*ValidateDataResourceConfig_Response)(nil), // 99: tfplugin6.ValidateDataResourceConfig.Response + (*ValidateEphemeralResourceConfig_Request)(nil), // 100: tfplugin6.ValidateEphemeralResourceConfig.Request + (*ValidateEphemeralResourceConfig_Response)(nil), // 101: tfplugin6.ValidateEphemeralResourceConfig.Response + (*ConfigureProvider_Request)(nil), // 102: tfplugin6.ConfigureProvider.Request + (*ConfigureProvider_Response)(nil), // 103: tfplugin6.ConfigureProvider.Response + (*ReadResource_Request)(nil), // 104: tfplugin6.ReadResource.Request + (*ReadResource_Response)(nil), // 105: tfplugin6.ReadResource.Response + (*PlanResourceChange_Request)(nil), // 106: tfplugin6.PlanResourceChange.Request + (*PlanResourceChange_Response)(nil), // 107: tfplugin6.PlanResourceChange.Response + (*ApplyResourceChange_Request)(nil), // 108: tfplugin6.ApplyResourceChange.Request + (*ApplyResourceChange_Response)(nil), // 109: tfplugin6.ApplyResourceChange.Response + (*ImportResourceState_Request)(nil), // 110: tfplugin6.ImportResourceState.Request + (*ImportResourceState_ImportedResource)(nil), // 111: tfplugin6.ImportResourceState.ImportedResource + (*ImportResourceState_Response)(nil), // 112: tfplugin6.ImportResourceState.Response + (*MoveResourceState_Request)(nil), // 113: tfplugin6.MoveResourceState.Request + (*MoveResourceState_Response)(nil), // 114: tfplugin6.MoveResourceState.Response + (*ReadDataSource_Request)(nil), // 115: tfplugin6.ReadDataSource.Request + (*ReadDataSource_Response)(nil), // 116: tfplugin6.ReadDataSource.Response + (*OpenEphemeralResource_Request)(nil), // 117: tfplugin6.OpenEphemeralResource.Request + (*OpenEphemeralResource_Response)(nil), // 118: tfplugin6.OpenEphemeralResource.Response + (*RenewEphemeralResource_Request)(nil), // 119: tfplugin6.RenewEphemeralResource.Request + (*RenewEphemeralResource_Response)(nil), // 120: tfplugin6.RenewEphemeralResource.Response + (*CloseEphemeralResource_Request)(nil), // 121: tfplugin6.CloseEphemeralResource.Request + (*CloseEphemeralResource_Response)(nil), // 122: tfplugin6.CloseEphemeralResource.Response + (*GetFunctions_Request)(nil), // 123: tfplugin6.GetFunctions.Request + (*GetFunctions_Response)(nil), // 124: tfplugin6.GetFunctions.Response + nil, // 125: tfplugin6.GetFunctions.Response.FunctionsEntry + (*CallFunction_Request)(nil), // 126: tfplugin6.CallFunction.Request + (*CallFunction_Response)(nil), // 127: tfplugin6.CallFunction.Response + (*ListResource_Request)(nil), // 128: tfplugin6.ListResource.Request + (*ListResource_Event)(nil), // 129: tfplugin6.ListResource.Event + (*ValidateListResourceConfig_Request)(nil), // 130: tfplugin6.ValidateListResourceConfig.Request + (*ValidateListResourceConfig_Response)(nil), // 131: tfplugin6.ValidateListResourceConfig.Response + (*ValidateStateStore_Request)(nil), // 132: tfplugin6.ValidateStateStore.Request + (*ValidateStateStore_Response)(nil), // 133: tfplugin6.ValidateStateStore.Response + (*ConfigureStateStore_Request)(nil), // 134: tfplugin6.ConfigureStateStore.Request + (*ConfigureStateStore_Response)(nil), // 135: tfplugin6.ConfigureStateStore.Response + (*ReadStateBytes_Request)(nil), // 136: tfplugin6.ReadStateBytes.Request + (*ReadStateBytes_Response)(nil), // 137: tfplugin6.ReadStateBytes.Response + (*WriteStateBytes_RequestChunk)(nil), // 138: tfplugin6.WriteStateBytes.RequestChunk + (*WriteStateBytes_Response)(nil), // 139: tfplugin6.WriteStateBytes.Response + (*GetStates_Request)(nil), // 140: tfplugin6.GetStates.Request + (*GetStates_Response)(nil), // 141: tfplugin6.GetStates.Response + (*DeleteState_Request)(nil), // 142: tfplugin6.DeleteState.Request + (*DeleteState_Response)(nil), // 143: tfplugin6.DeleteState.Response + (*PlanAction_Request)(nil), // 144: tfplugin6.PlanAction.Request + (*PlanAction_Response)(nil), // 145: tfplugin6.PlanAction.Response + (*PlanAction_Request_LinkedResource)(nil), // 146: tfplugin6.PlanAction.Request.LinkedResource + (*PlanAction_Response_LinkedResource)(nil), // 147: tfplugin6.PlanAction.Response.LinkedResource + (*InvokeAction_Request)(nil), // 148: tfplugin6.InvokeAction.Request + (*InvokeAction_Event)(nil), // 149: tfplugin6.InvokeAction.Event + (*InvokeAction_Request_LinkedResource)(nil), // 150: tfplugin6.InvokeAction.Request.LinkedResource + (*InvokeAction_Event_Progress)(nil), // 151: tfplugin6.InvokeAction.Event.Progress + (*InvokeAction_Event_Completed)(nil), // 152: tfplugin6.InvokeAction.Event.Completed + (*InvokeAction_Event_Completed_LinkedResource)(nil), // 153: tfplugin6.InvokeAction.Event.Completed.LinkedResource + (*ValidateActionConfig_Request)(nil), // 154: tfplugin6.ValidateActionConfig.Request + (*ValidateActionConfig_Response)(nil), // 155: tfplugin6.ValidateActionConfig.Response + (*timestamppb.Timestamp)(nil), // 156: google.protobuf.Timestamp } var file_tfplugin6_proto_depIdxs = []int32{ 1, // 0: tfplugin6.Diagnostic.severity:type_name -> tfplugin6.Diagnostic.Severity 9, // 1: tfplugin6.Diagnostic.attribute:type_name -> tfplugin6.AttributePath - 51, // 2: tfplugin6.AttributePath.steps:type_name -> tfplugin6.AttributePath.Step - 54, // 3: tfplugin6.RawState.flatmap:type_name -> tfplugin6.RawState.FlatmapEntry - 55, // 4: tfplugin6.ResourceIdentitySchema.identity_attributes:type_name -> tfplugin6.ResourceIdentitySchema.IdentityAttribute + 54, // 2: tfplugin6.AttributePath.steps:type_name -> tfplugin6.AttributePath.Step + 57, // 3: tfplugin6.RawState.flatmap:type_name -> tfplugin6.RawState.FlatmapEntry + 58, // 4: tfplugin6.ResourceIdentitySchema.identity_attributes:type_name -> tfplugin6.ResourceIdentitySchema.IdentityAttribute 6, // 5: tfplugin6.ResourceIdentityData.identity_data:type_name -> tfplugin6.DynamicValue 15, // 6: tfplugin6.ActionSchema.schema:type_name -> tfplugin6.Schema - 57, // 7: tfplugin6.ActionSchema.unlinked:type_name -> tfplugin6.ActionSchema.Unlinked - 58, // 8: tfplugin6.ActionSchema.lifecycle:type_name -> tfplugin6.ActionSchema.Lifecycle - 59, // 9: tfplugin6.ActionSchema.linked:type_name -> tfplugin6.ActionSchema.Linked - 60, // 10: tfplugin6.Schema.block:type_name -> tfplugin6.Schema.Block - 64, // 11: tfplugin6.Function.parameters:type_name -> tfplugin6.Function.Parameter - 64, // 12: tfplugin6.Function.variadic_parameter:type_name -> tfplugin6.Function.Parameter - 65, // 13: tfplugin6.Function.return:type_name -> tfplugin6.Function.Return + 60, // 7: tfplugin6.ActionSchema.unlinked:type_name -> tfplugin6.ActionSchema.Unlinked + 61, // 8: tfplugin6.ActionSchema.lifecycle:type_name -> tfplugin6.ActionSchema.Lifecycle + 62, // 9: tfplugin6.ActionSchema.linked:type_name -> tfplugin6.ActionSchema.Linked + 63, // 10: tfplugin6.Schema.block:type_name -> tfplugin6.Schema.Block + 67, // 11: tfplugin6.Function.parameters:type_name -> tfplugin6.Function.Parameter + 67, // 12: tfplugin6.Function.variadic_parameter:type_name -> tfplugin6.Function.Parameter + 68, // 13: tfplugin6.Function.return:type_name -> tfplugin6.Function.Return 0, // 14: tfplugin6.Function.description_kind:type_name -> tfplugin6.StringKind 5, // 15: tfplugin6.Deferred.reason:type_name -> tfplugin6.Deferred.Reason 6, // 16: tfplugin6.LinkedResourceConfig.config:type_name -> tfplugin6.DynamicValue 2, // 17: tfplugin6.ActionSchema.Lifecycle.executes:type_name -> tfplugin6.ActionSchema.Lifecycle.ExecutionOrder - 56, // 18: tfplugin6.ActionSchema.Lifecycle.linked_resource:type_name -> tfplugin6.ActionSchema.LinkedResource - 56, // 19: tfplugin6.ActionSchema.Linked.linked_resources:type_name -> tfplugin6.ActionSchema.LinkedResource - 61, // 20: tfplugin6.Schema.Block.attributes:type_name -> tfplugin6.Schema.Attribute - 62, // 21: tfplugin6.Schema.Block.block_types:type_name -> tfplugin6.Schema.NestedBlock + 59, // 18: tfplugin6.ActionSchema.Lifecycle.linked_resource:type_name -> tfplugin6.ActionSchema.LinkedResource + 59, // 19: tfplugin6.ActionSchema.Linked.linked_resources:type_name -> tfplugin6.ActionSchema.LinkedResource + 64, // 20: tfplugin6.Schema.Block.attributes:type_name -> tfplugin6.Schema.Attribute + 65, // 21: tfplugin6.Schema.Block.block_types:type_name -> tfplugin6.Schema.NestedBlock 0, // 22: tfplugin6.Schema.Block.description_kind:type_name -> tfplugin6.StringKind - 63, // 23: tfplugin6.Schema.Attribute.nested_type:type_name -> tfplugin6.Schema.Object + 66, // 23: tfplugin6.Schema.Attribute.nested_type:type_name -> tfplugin6.Schema.Object 0, // 24: tfplugin6.Schema.Attribute.description_kind:type_name -> tfplugin6.StringKind - 60, // 25: tfplugin6.Schema.NestedBlock.block:type_name -> tfplugin6.Schema.Block + 63, // 25: tfplugin6.Schema.NestedBlock.block:type_name -> tfplugin6.Schema.Block 3, // 26: tfplugin6.Schema.NestedBlock.nesting:type_name -> tfplugin6.Schema.NestedBlock.NestingMode - 61, // 27: tfplugin6.Schema.Object.attributes:type_name -> tfplugin6.Schema.Attribute + 64, // 27: tfplugin6.Schema.Object.attributes:type_name -> tfplugin6.Schema.Attribute 4, // 28: tfplugin6.Schema.Object.nesting:type_name -> tfplugin6.Schema.Object.NestingMode 0, // 29: tfplugin6.Function.Parameter.description_kind:type_name -> tfplugin6.StringKind 17, // 30: tfplugin6.GetMetadata.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities 7, // 31: tfplugin6.GetMetadata.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 70, // 32: tfplugin6.GetMetadata.Response.data_sources:type_name -> tfplugin6.GetMetadata.DataSourceMetadata - 71, // 33: tfplugin6.GetMetadata.Response.resources:type_name -> tfplugin6.GetMetadata.ResourceMetadata - 69, // 34: tfplugin6.GetMetadata.Response.functions:type_name -> tfplugin6.GetMetadata.FunctionMetadata - 68, // 35: tfplugin6.GetMetadata.Response.ephemeral_resources:type_name -> tfplugin6.GetMetadata.EphemeralMetadata - 72, // 36: tfplugin6.GetMetadata.Response.list_resources:type_name -> tfplugin6.GetMetadata.ListResourceMetadata - 73, // 37: tfplugin6.GetMetadata.Response.state_stores:type_name -> tfplugin6.GetMetadata.StateStoreMetadata - 74, // 38: tfplugin6.GetMetadata.Response.actions:type_name -> tfplugin6.GetMetadata.ActionMetadata + 73, // 32: tfplugin6.GetMetadata.Response.data_sources:type_name -> tfplugin6.GetMetadata.DataSourceMetadata + 74, // 33: tfplugin6.GetMetadata.Response.resources:type_name -> tfplugin6.GetMetadata.ResourceMetadata + 72, // 34: tfplugin6.GetMetadata.Response.functions:type_name -> tfplugin6.GetMetadata.FunctionMetadata + 71, // 35: tfplugin6.GetMetadata.Response.ephemeral_resources:type_name -> tfplugin6.GetMetadata.EphemeralMetadata + 75, // 36: tfplugin6.GetMetadata.Response.list_resources:type_name -> tfplugin6.GetMetadata.ListResourceMetadata + 76, // 37: tfplugin6.GetMetadata.Response.state_stores:type_name -> tfplugin6.GetMetadata.StateStoreMetadata + 77, // 38: tfplugin6.GetMetadata.Response.actions:type_name -> tfplugin6.GetMetadata.ActionMetadata 15, // 39: tfplugin6.GetProviderSchema.Response.provider:type_name -> tfplugin6.Schema - 77, // 40: tfplugin6.GetProviderSchema.Response.resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry - 78, // 41: tfplugin6.GetProviderSchema.Response.data_source_schemas:type_name -> tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry - 79, // 42: tfplugin6.GetProviderSchema.Response.functions:type_name -> tfplugin6.GetProviderSchema.Response.FunctionsEntry - 80, // 43: tfplugin6.GetProviderSchema.Response.ephemeral_resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.EphemeralResourceSchemasEntry - 81, // 44: tfplugin6.GetProviderSchema.Response.list_resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ListResourceSchemasEntry - 82, // 45: tfplugin6.GetProviderSchema.Response.state_store_schemas:type_name -> tfplugin6.GetProviderSchema.Response.StateStoreSchemasEntry - 83, // 46: tfplugin6.GetProviderSchema.Response.action_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ActionSchemasEntry + 80, // 40: tfplugin6.GetProviderSchema.Response.resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry + 81, // 41: tfplugin6.GetProviderSchema.Response.data_source_schemas:type_name -> tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry + 82, // 42: tfplugin6.GetProviderSchema.Response.functions:type_name -> tfplugin6.GetProviderSchema.Response.FunctionsEntry + 83, // 43: tfplugin6.GetProviderSchema.Response.ephemeral_resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.EphemeralResourceSchemasEntry + 84, // 44: tfplugin6.GetProviderSchema.Response.list_resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ListResourceSchemasEntry + 85, // 45: tfplugin6.GetProviderSchema.Response.state_store_schemas:type_name -> tfplugin6.GetProviderSchema.Response.StateStoreSchemasEntry + 86, // 46: tfplugin6.GetProviderSchema.Response.action_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ActionSchemasEntry 7, // 47: tfplugin6.GetProviderSchema.Response.diagnostics:type_name -> tfplugin6.Diagnostic 15, // 48: tfplugin6.GetProviderSchema.Response.provider_meta:type_name -> tfplugin6.Schema 17, // 49: tfplugin6.GetProviderSchema.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities @@ -8560,7 +8956,7 @@ var file_tfplugin6_proto_depIdxs = []int32{ 11, // 59: tfplugin6.UpgradeResourceState.Request.raw_state:type_name -> tfplugin6.RawState 6, // 60: tfplugin6.UpgradeResourceState.Response.upgraded_state:type_name -> tfplugin6.DynamicValue 7, // 61: tfplugin6.UpgradeResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 90, // 62: tfplugin6.GetResourceIdentitySchemas.Response.identity_schemas:type_name -> tfplugin6.GetResourceIdentitySchemas.Response.IdentitySchemasEntry + 93, // 62: tfplugin6.GetResourceIdentitySchemas.Response.identity_schemas:type_name -> tfplugin6.GetResourceIdentitySchemas.Response.IdentitySchemasEntry 7, // 63: tfplugin6.GetResourceIdentitySchemas.Response.diagnostics:type_name -> tfplugin6.Diagnostic 12, // 64: tfplugin6.GetResourceIdentitySchemas.Response.IdentitySchemasEntry.value:type_name -> tfplugin6.ResourceIdentitySchema 11, // 65: tfplugin6.UpgradeResourceIdentity.Request.raw_identity:type_name -> tfplugin6.RawState @@ -8607,7 +9003,7 @@ var file_tfplugin6_proto_depIdxs = []int32{ 13, // 106: tfplugin6.ImportResourceState.Request.identity:type_name -> tfplugin6.ResourceIdentityData 6, // 107: tfplugin6.ImportResourceState.ImportedResource.state:type_name -> tfplugin6.DynamicValue 13, // 108: tfplugin6.ImportResourceState.ImportedResource.identity:type_name -> tfplugin6.ResourceIdentityData - 108, // 109: tfplugin6.ImportResourceState.Response.imported_resources:type_name -> tfplugin6.ImportResourceState.ImportedResource + 111, // 109: tfplugin6.ImportResourceState.Response.imported_resources:type_name -> tfplugin6.ImportResourceState.ImportedResource 7, // 110: tfplugin6.ImportResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic 19, // 111: tfplugin6.ImportResourceState.Response.deferred:type_name -> tfplugin6.Deferred 11, // 112: tfplugin6.MoveResourceState.Request.source_state:type_name -> tfplugin6.RawState @@ -8624,13 +9020,13 @@ var file_tfplugin6_proto_depIdxs = []int32{ 6, // 123: tfplugin6.OpenEphemeralResource.Request.config:type_name -> tfplugin6.DynamicValue 18, // 124: tfplugin6.OpenEphemeralResource.Request.client_capabilities:type_name -> tfplugin6.ClientCapabilities 7, // 125: tfplugin6.OpenEphemeralResource.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 149, // 126: tfplugin6.OpenEphemeralResource.Response.renew_at:type_name -> google.protobuf.Timestamp + 156, // 126: tfplugin6.OpenEphemeralResource.Response.renew_at:type_name -> google.protobuf.Timestamp 6, // 127: tfplugin6.OpenEphemeralResource.Response.result:type_name -> tfplugin6.DynamicValue 19, // 128: tfplugin6.OpenEphemeralResource.Response.deferred:type_name -> tfplugin6.Deferred 7, // 129: tfplugin6.RenewEphemeralResource.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 149, // 130: tfplugin6.RenewEphemeralResource.Response.renew_at:type_name -> google.protobuf.Timestamp + 156, // 130: tfplugin6.RenewEphemeralResource.Response.renew_at:type_name -> google.protobuf.Timestamp 7, // 131: tfplugin6.CloseEphemeralResource.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 122, // 132: tfplugin6.GetFunctions.Response.functions:type_name -> tfplugin6.GetFunctions.Response.FunctionsEntry + 125, // 132: tfplugin6.GetFunctions.Response.functions:type_name -> tfplugin6.GetFunctions.Response.FunctionsEntry 7, // 133: tfplugin6.GetFunctions.Response.diagnostics:type_name -> tfplugin6.Diagnostic 16, // 134: tfplugin6.GetFunctions.Response.FunctionsEntry.value:type_name -> tfplugin6.Function 6, // 135: tfplugin6.CallFunction.Request.arguments:type_name -> tfplugin6.DynamicValue @@ -8648,103 +9044,111 @@ var file_tfplugin6_proto_depIdxs = []int32{ 7, // 147: tfplugin6.ValidateStateStore.Response.diagnostics:type_name -> tfplugin6.Diagnostic 6, // 148: tfplugin6.ConfigureStateStore.Request.config:type_name -> tfplugin6.DynamicValue 7, // 149: tfplugin6.ConfigureStateStore.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 7, // 150: tfplugin6.GetStates.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 7, // 151: tfplugin6.DeleteState.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 139, // 152: tfplugin6.PlanAction.Request.linked_resources:type_name -> tfplugin6.PlanAction.Request.LinkedResource - 6, // 153: tfplugin6.PlanAction.Request.config:type_name -> tfplugin6.DynamicValue - 18, // 154: tfplugin6.PlanAction.Request.client_capabilities:type_name -> tfplugin6.ClientCapabilities - 140, // 155: tfplugin6.PlanAction.Response.linked_resources:type_name -> tfplugin6.PlanAction.Response.LinkedResource - 7, // 156: tfplugin6.PlanAction.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 19, // 157: tfplugin6.PlanAction.Response.deferred:type_name -> tfplugin6.Deferred - 6, // 158: tfplugin6.PlanAction.Request.LinkedResource.prior_state:type_name -> tfplugin6.DynamicValue - 6, // 159: tfplugin6.PlanAction.Request.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue - 6, // 160: tfplugin6.PlanAction.Request.LinkedResource.config:type_name -> tfplugin6.DynamicValue - 13, // 161: tfplugin6.PlanAction.Request.LinkedResource.prior_identity:type_name -> tfplugin6.ResourceIdentityData - 6, // 162: tfplugin6.PlanAction.Response.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue - 13, // 163: tfplugin6.PlanAction.Response.LinkedResource.planned_identity:type_name -> tfplugin6.ResourceIdentityData - 143, // 164: tfplugin6.InvokeAction.Request.linked_resources:type_name -> tfplugin6.InvokeAction.Request.LinkedResource - 6, // 165: tfplugin6.InvokeAction.Request.config:type_name -> tfplugin6.DynamicValue - 18, // 166: tfplugin6.InvokeAction.Request.client_capabilities:type_name -> tfplugin6.ClientCapabilities - 144, // 167: tfplugin6.InvokeAction.Event.progress:type_name -> tfplugin6.InvokeAction.Event.Progress - 145, // 168: tfplugin6.InvokeAction.Event.completed:type_name -> tfplugin6.InvokeAction.Event.Completed - 6, // 169: tfplugin6.InvokeAction.Request.LinkedResource.prior_state:type_name -> tfplugin6.DynamicValue - 6, // 170: tfplugin6.InvokeAction.Request.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue - 6, // 171: tfplugin6.InvokeAction.Request.LinkedResource.config:type_name -> tfplugin6.DynamicValue - 13, // 172: tfplugin6.InvokeAction.Request.LinkedResource.planned_identity:type_name -> tfplugin6.ResourceIdentityData - 146, // 173: tfplugin6.InvokeAction.Event.Completed.linked_resources:type_name -> tfplugin6.InvokeAction.Event.Completed.LinkedResource - 7, // 174: tfplugin6.InvokeAction.Event.Completed.diagnostics:type_name -> tfplugin6.Diagnostic - 6, // 175: tfplugin6.InvokeAction.Event.Completed.LinkedResource.new_state:type_name -> tfplugin6.DynamicValue - 13, // 176: tfplugin6.InvokeAction.Event.Completed.LinkedResource.new_identity:type_name -> tfplugin6.ResourceIdentityData - 6, // 177: tfplugin6.ValidateActionConfig.Request.config:type_name -> tfplugin6.DynamicValue - 50, // 178: tfplugin6.ValidateActionConfig.Request.linked_resources:type_name -> tfplugin6.LinkedResourceConfig - 7, // 179: tfplugin6.ValidateActionConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 66, // 180: tfplugin6.Provider.GetMetadata:input_type -> tfplugin6.GetMetadata.Request - 75, // 181: tfplugin6.Provider.GetProviderSchema:input_type -> tfplugin6.GetProviderSchema.Request - 84, // 182: tfplugin6.Provider.ValidateProviderConfig:input_type -> tfplugin6.ValidateProviderConfig.Request - 93, // 183: tfplugin6.Provider.ValidateResourceConfig:input_type -> tfplugin6.ValidateResourceConfig.Request - 95, // 184: tfplugin6.Provider.ValidateDataResourceConfig:input_type -> tfplugin6.ValidateDataResourceConfig.Request - 86, // 185: tfplugin6.Provider.UpgradeResourceState:input_type -> tfplugin6.UpgradeResourceState.Request - 88, // 186: tfplugin6.Provider.GetResourceIdentitySchemas:input_type -> tfplugin6.GetResourceIdentitySchemas.Request - 91, // 187: tfplugin6.Provider.UpgradeResourceIdentity:input_type -> tfplugin6.UpgradeResourceIdentity.Request - 99, // 188: tfplugin6.Provider.ConfigureProvider:input_type -> tfplugin6.ConfigureProvider.Request - 101, // 189: tfplugin6.Provider.ReadResource:input_type -> tfplugin6.ReadResource.Request - 103, // 190: tfplugin6.Provider.PlanResourceChange:input_type -> tfplugin6.PlanResourceChange.Request - 105, // 191: tfplugin6.Provider.ApplyResourceChange:input_type -> tfplugin6.ApplyResourceChange.Request - 107, // 192: tfplugin6.Provider.ImportResourceState:input_type -> tfplugin6.ImportResourceState.Request - 110, // 193: tfplugin6.Provider.MoveResourceState:input_type -> tfplugin6.MoveResourceState.Request - 112, // 194: tfplugin6.Provider.ReadDataSource:input_type -> tfplugin6.ReadDataSource.Request - 97, // 195: tfplugin6.Provider.ValidateEphemeralResourceConfig:input_type -> tfplugin6.ValidateEphemeralResourceConfig.Request - 114, // 196: tfplugin6.Provider.OpenEphemeralResource:input_type -> tfplugin6.OpenEphemeralResource.Request - 116, // 197: tfplugin6.Provider.RenewEphemeralResource:input_type -> tfplugin6.RenewEphemeralResource.Request - 118, // 198: tfplugin6.Provider.CloseEphemeralResource:input_type -> tfplugin6.CloseEphemeralResource.Request - 125, // 199: tfplugin6.Provider.ListResource:input_type -> tfplugin6.ListResource.Request - 127, // 200: tfplugin6.Provider.ValidateListResourceConfig:input_type -> tfplugin6.ValidateListResourceConfig.Request - 120, // 201: tfplugin6.Provider.GetFunctions:input_type -> tfplugin6.GetFunctions.Request - 123, // 202: tfplugin6.Provider.CallFunction:input_type -> tfplugin6.CallFunction.Request - 129, // 203: tfplugin6.Provider.ValidateStateStoreConfig:input_type -> tfplugin6.ValidateStateStore.Request - 131, // 204: tfplugin6.Provider.ConfigureStateStore:input_type -> tfplugin6.ConfigureStateStore.Request - 133, // 205: tfplugin6.Provider.GetStates:input_type -> tfplugin6.GetStates.Request - 135, // 206: tfplugin6.Provider.DeleteState:input_type -> tfplugin6.DeleteState.Request - 137, // 207: tfplugin6.Provider.PlanAction:input_type -> tfplugin6.PlanAction.Request - 141, // 208: tfplugin6.Provider.InvokeAction:input_type -> tfplugin6.InvokeAction.Request - 147, // 209: tfplugin6.Provider.ValidateActionConfig:input_type -> tfplugin6.ValidateActionConfig.Request - 52, // 210: tfplugin6.Provider.StopProvider:input_type -> tfplugin6.StopProvider.Request - 67, // 211: tfplugin6.Provider.GetMetadata:output_type -> tfplugin6.GetMetadata.Response - 76, // 212: tfplugin6.Provider.GetProviderSchema:output_type -> tfplugin6.GetProviderSchema.Response - 85, // 213: tfplugin6.Provider.ValidateProviderConfig:output_type -> tfplugin6.ValidateProviderConfig.Response - 94, // 214: tfplugin6.Provider.ValidateResourceConfig:output_type -> tfplugin6.ValidateResourceConfig.Response - 96, // 215: tfplugin6.Provider.ValidateDataResourceConfig:output_type -> tfplugin6.ValidateDataResourceConfig.Response - 87, // 216: tfplugin6.Provider.UpgradeResourceState:output_type -> tfplugin6.UpgradeResourceState.Response - 89, // 217: tfplugin6.Provider.GetResourceIdentitySchemas:output_type -> tfplugin6.GetResourceIdentitySchemas.Response - 92, // 218: tfplugin6.Provider.UpgradeResourceIdentity:output_type -> tfplugin6.UpgradeResourceIdentity.Response - 100, // 219: tfplugin6.Provider.ConfigureProvider:output_type -> tfplugin6.ConfigureProvider.Response - 102, // 220: tfplugin6.Provider.ReadResource:output_type -> tfplugin6.ReadResource.Response - 104, // 221: tfplugin6.Provider.PlanResourceChange:output_type -> tfplugin6.PlanResourceChange.Response - 106, // 222: tfplugin6.Provider.ApplyResourceChange:output_type -> tfplugin6.ApplyResourceChange.Response - 109, // 223: tfplugin6.Provider.ImportResourceState:output_type -> tfplugin6.ImportResourceState.Response - 111, // 224: tfplugin6.Provider.MoveResourceState:output_type -> tfplugin6.MoveResourceState.Response - 113, // 225: tfplugin6.Provider.ReadDataSource:output_type -> tfplugin6.ReadDataSource.Response - 98, // 226: tfplugin6.Provider.ValidateEphemeralResourceConfig:output_type -> tfplugin6.ValidateEphemeralResourceConfig.Response - 115, // 227: tfplugin6.Provider.OpenEphemeralResource:output_type -> tfplugin6.OpenEphemeralResource.Response - 117, // 228: tfplugin6.Provider.RenewEphemeralResource:output_type -> tfplugin6.RenewEphemeralResource.Response - 119, // 229: tfplugin6.Provider.CloseEphemeralResource:output_type -> tfplugin6.CloseEphemeralResource.Response - 126, // 230: tfplugin6.Provider.ListResource:output_type -> tfplugin6.ListResource.Event - 128, // 231: tfplugin6.Provider.ValidateListResourceConfig:output_type -> tfplugin6.ValidateListResourceConfig.Response - 121, // 232: tfplugin6.Provider.GetFunctions:output_type -> tfplugin6.GetFunctions.Response - 124, // 233: tfplugin6.Provider.CallFunction:output_type -> tfplugin6.CallFunction.Response - 130, // 234: tfplugin6.Provider.ValidateStateStoreConfig:output_type -> tfplugin6.ValidateStateStore.Response - 132, // 235: tfplugin6.Provider.ConfigureStateStore:output_type -> tfplugin6.ConfigureStateStore.Response - 134, // 236: tfplugin6.Provider.GetStates:output_type -> tfplugin6.GetStates.Response - 136, // 237: tfplugin6.Provider.DeleteState:output_type -> tfplugin6.DeleteState.Response - 138, // 238: tfplugin6.Provider.PlanAction:output_type -> tfplugin6.PlanAction.Response - 142, // 239: tfplugin6.Provider.InvokeAction:output_type -> tfplugin6.InvokeAction.Event - 148, // 240: tfplugin6.Provider.ValidateActionConfig:output_type -> tfplugin6.ValidateActionConfig.Response - 53, // 241: tfplugin6.Provider.StopProvider:output_type -> tfplugin6.StopProvider.Response - 211, // [211:242] is the sub-list for method output_type - 180, // [180:211] is the sub-list for method input_type - 180, // [180:180] is the sub-list for extension type_name - 180, // [180:180] is the sub-list for extension extendee - 0, // [0:180] is the sub-list for field type_name + 47, // 150: tfplugin6.ReadStateBytes.Response.range:type_name -> tfplugin6.StateRange + 7, // 151: tfplugin6.ReadStateBytes.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 47, // 152: tfplugin6.WriteStateBytes.RequestChunk.range:type_name -> tfplugin6.StateRange + 7, // 153: tfplugin6.WriteStateBytes.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 7, // 154: tfplugin6.GetStates.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 7, // 155: tfplugin6.DeleteState.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 146, // 156: tfplugin6.PlanAction.Request.linked_resources:type_name -> tfplugin6.PlanAction.Request.LinkedResource + 6, // 157: tfplugin6.PlanAction.Request.config:type_name -> tfplugin6.DynamicValue + 18, // 158: tfplugin6.PlanAction.Request.client_capabilities:type_name -> tfplugin6.ClientCapabilities + 147, // 159: tfplugin6.PlanAction.Response.linked_resources:type_name -> tfplugin6.PlanAction.Response.LinkedResource + 7, // 160: tfplugin6.PlanAction.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 19, // 161: tfplugin6.PlanAction.Response.deferred:type_name -> tfplugin6.Deferred + 6, // 162: tfplugin6.PlanAction.Request.LinkedResource.prior_state:type_name -> tfplugin6.DynamicValue + 6, // 163: tfplugin6.PlanAction.Request.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue + 6, // 164: tfplugin6.PlanAction.Request.LinkedResource.config:type_name -> tfplugin6.DynamicValue + 13, // 165: tfplugin6.PlanAction.Request.LinkedResource.prior_identity:type_name -> tfplugin6.ResourceIdentityData + 6, // 166: tfplugin6.PlanAction.Response.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue + 13, // 167: tfplugin6.PlanAction.Response.LinkedResource.planned_identity:type_name -> tfplugin6.ResourceIdentityData + 150, // 168: tfplugin6.InvokeAction.Request.linked_resources:type_name -> tfplugin6.InvokeAction.Request.LinkedResource + 6, // 169: tfplugin6.InvokeAction.Request.config:type_name -> tfplugin6.DynamicValue + 18, // 170: tfplugin6.InvokeAction.Request.client_capabilities:type_name -> tfplugin6.ClientCapabilities + 151, // 171: tfplugin6.InvokeAction.Event.progress:type_name -> tfplugin6.InvokeAction.Event.Progress + 152, // 172: tfplugin6.InvokeAction.Event.completed:type_name -> tfplugin6.InvokeAction.Event.Completed + 6, // 173: tfplugin6.InvokeAction.Request.LinkedResource.prior_state:type_name -> tfplugin6.DynamicValue + 6, // 174: tfplugin6.InvokeAction.Request.LinkedResource.planned_state:type_name -> tfplugin6.DynamicValue + 6, // 175: tfplugin6.InvokeAction.Request.LinkedResource.config:type_name -> tfplugin6.DynamicValue + 13, // 176: tfplugin6.InvokeAction.Request.LinkedResource.planned_identity:type_name -> tfplugin6.ResourceIdentityData + 153, // 177: tfplugin6.InvokeAction.Event.Completed.linked_resources:type_name -> tfplugin6.InvokeAction.Event.Completed.LinkedResource + 7, // 178: tfplugin6.InvokeAction.Event.Completed.diagnostics:type_name -> tfplugin6.Diagnostic + 6, // 179: tfplugin6.InvokeAction.Event.Completed.LinkedResource.new_state:type_name -> tfplugin6.DynamicValue + 13, // 180: tfplugin6.InvokeAction.Event.Completed.LinkedResource.new_identity:type_name -> tfplugin6.ResourceIdentityData + 6, // 181: tfplugin6.ValidateActionConfig.Request.config:type_name -> tfplugin6.DynamicValue + 53, // 182: tfplugin6.ValidateActionConfig.Request.linked_resources:type_name -> tfplugin6.LinkedResourceConfig + 7, // 183: tfplugin6.ValidateActionConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 69, // 184: tfplugin6.Provider.GetMetadata:input_type -> tfplugin6.GetMetadata.Request + 78, // 185: tfplugin6.Provider.GetProviderSchema:input_type -> tfplugin6.GetProviderSchema.Request + 87, // 186: tfplugin6.Provider.ValidateProviderConfig:input_type -> tfplugin6.ValidateProviderConfig.Request + 96, // 187: tfplugin6.Provider.ValidateResourceConfig:input_type -> tfplugin6.ValidateResourceConfig.Request + 98, // 188: tfplugin6.Provider.ValidateDataResourceConfig:input_type -> tfplugin6.ValidateDataResourceConfig.Request + 89, // 189: tfplugin6.Provider.UpgradeResourceState:input_type -> tfplugin6.UpgradeResourceState.Request + 91, // 190: tfplugin6.Provider.GetResourceIdentitySchemas:input_type -> tfplugin6.GetResourceIdentitySchemas.Request + 94, // 191: tfplugin6.Provider.UpgradeResourceIdentity:input_type -> tfplugin6.UpgradeResourceIdentity.Request + 102, // 192: tfplugin6.Provider.ConfigureProvider:input_type -> tfplugin6.ConfigureProvider.Request + 104, // 193: tfplugin6.Provider.ReadResource:input_type -> tfplugin6.ReadResource.Request + 106, // 194: tfplugin6.Provider.PlanResourceChange:input_type -> tfplugin6.PlanResourceChange.Request + 108, // 195: tfplugin6.Provider.ApplyResourceChange:input_type -> tfplugin6.ApplyResourceChange.Request + 110, // 196: tfplugin6.Provider.ImportResourceState:input_type -> tfplugin6.ImportResourceState.Request + 113, // 197: tfplugin6.Provider.MoveResourceState:input_type -> tfplugin6.MoveResourceState.Request + 115, // 198: tfplugin6.Provider.ReadDataSource:input_type -> tfplugin6.ReadDataSource.Request + 100, // 199: tfplugin6.Provider.ValidateEphemeralResourceConfig:input_type -> tfplugin6.ValidateEphemeralResourceConfig.Request + 117, // 200: tfplugin6.Provider.OpenEphemeralResource:input_type -> tfplugin6.OpenEphemeralResource.Request + 119, // 201: tfplugin6.Provider.RenewEphemeralResource:input_type -> tfplugin6.RenewEphemeralResource.Request + 121, // 202: tfplugin6.Provider.CloseEphemeralResource:input_type -> tfplugin6.CloseEphemeralResource.Request + 128, // 203: tfplugin6.Provider.ListResource:input_type -> tfplugin6.ListResource.Request + 130, // 204: tfplugin6.Provider.ValidateListResourceConfig:input_type -> tfplugin6.ValidateListResourceConfig.Request + 123, // 205: tfplugin6.Provider.GetFunctions:input_type -> tfplugin6.GetFunctions.Request + 126, // 206: tfplugin6.Provider.CallFunction:input_type -> tfplugin6.CallFunction.Request + 132, // 207: tfplugin6.Provider.ValidateStateStoreConfig:input_type -> tfplugin6.ValidateStateStore.Request + 134, // 208: tfplugin6.Provider.ConfigureStateStore:input_type -> tfplugin6.ConfigureStateStore.Request + 136, // 209: tfplugin6.Provider.ReadStateBytes:input_type -> tfplugin6.ReadStateBytes.Request + 138, // 210: tfplugin6.Provider.WriteStateBytes:input_type -> tfplugin6.WriteStateBytes.RequestChunk + 140, // 211: tfplugin6.Provider.GetStates:input_type -> tfplugin6.GetStates.Request + 142, // 212: tfplugin6.Provider.DeleteState:input_type -> tfplugin6.DeleteState.Request + 144, // 213: tfplugin6.Provider.PlanAction:input_type -> tfplugin6.PlanAction.Request + 148, // 214: tfplugin6.Provider.InvokeAction:input_type -> tfplugin6.InvokeAction.Request + 154, // 215: tfplugin6.Provider.ValidateActionConfig:input_type -> tfplugin6.ValidateActionConfig.Request + 55, // 216: tfplugin6.Provider.StopProvider:input_type -> tfplugin6.StopProvider.Request + 70, // 217: tfplugin6.Provider.GetMetadata:output_type -> tfplugin6.GetMetadata.Response + 79, // 218: tfplugin6.Provider.GetProviderSchema:output_type -> tfplugin6.GetProviderSchema.Response + 88, // 219: tfplugin6.Provider.ValidateProviderConfig:output_type -> tfplugin6.ValidateProviderConfig.Response + 97, // 220: tfplugin6.Provider.ValidateResourceConfig:output_type -> tfplugin6.ValidateResourceConfig.Response + 99, // 221: tfplugin6.Provider.ValidateDataResourceConfig:output_type -> tfplugin6.ValidateDataResourceConfig.Response + 90, // 222: tfplugin6.Provider.UpgradeResourceState:output_type -> tfplugin6.UpgradeResourceState.Response + 92, // 223: tfplugin6.Provider.GetResourceIdentitySchemas:output_type -> tfplugin6.GetResourceIdentitySchemas.Response + 95, // 224: tfplugin6.Provider.UpgradeResourceIdentity:output_type -> tfplugin6.UpgradeResourceIdentity.Response + 103, // 225: tfplugin6.Provider.ConfigureProvider:output_type -> tfplugin6.ConfigureProvider.Response + 105, // 226: tfplugin6.Provider.ReadResource:output_type -> tfplugin6.ReadResource.Response + 107, // 227: tfplugin6.Provider.PlanResourceChange:output_type -> tfplugin6.PlanResourceChange.Response + 109, // 228: tfplugin6.Provider.ApplyResourceChange:output_type -> tfplugin6.ApplyResourceChange.Response + 112, // 229: tfplugin6.Provider.ImportResourceState:output_type -> tfplugin6.ImportResourceState.Response + 114, // 230: tfplugin6.Provider.MoveResourceState:output_type -> tfplugin6.MoveResourceState.Response + 116, // 231: tfplugin6.Provider.ReadDataSource:output_type -> tfplugin6.ReadDataSource.Response + 101, // 232: tfplugin6.Provider.ValidateEphemeralResourceConfig:output_type -> tfplugin6.ValidateEphemeralResourceConfig.Response + 118, // 233: tfplugin6.Provider.OpenEphemeralResource:output_type -> tfplugin6.OpenEphemeralResource.Response + 120, // 234: tfplugin6.Provider.RenewEphemeralResource:output_type -> tfplugin6.RenewEphemeralResource.Response + 122, // 235: tfplugin6.Provider.CloseEphemeralResource:output_type -> tfplugin6.CloseEphemeralResource.Response + 129, // 236: tfplugin6.Provider.ListResource:output_type -> tfplugin6.ListResource.Event + 131, // 237: tfplugin6.Provider.ValidateListResourceConfig:output_type -> tfplugin6.ValidateListResourceConfig.Response + 124, // 238: tfplugin6.Provider.GetFunctions:output_type -> tfplugin6.GetFunctions.Response + 127, // 239: tfplugin6.Provider.CallFunction:output_type -> tfplugin6.CallFunction.Response + 133, // 240: tfplugin6.Provider.ValidateStateStoreConfig:output_type -> tfplugin6.ValidateStateStore.Response + 135, // 241: tfplugin6.Provider.ConfigureStateStore:output_type -> tfplugin6.ConfigureStateStore.Response + 137, // 242: tfplugin6.Provider.ReadStateBytes:output_type -> tfplugin6.ReadStateBytes.Response + 139, // 243: tfplugin6.Provider.WriteStateBytes:output_type -> tfplugin6.WriteStateBytes.Response + 141, // 244: tfplugin6.Provider.GetStates:output_type -> tfplugin6.GetStates.Response + 143, // 245: tfplugin6.Provider.DeleteState:output_type -> tfplugin6.DeleteState.Response + 145, // 246: tfplugin6.Provider.PlanAction:output_type -> tfplugin6.PlanAction.Response + 149, // 247: tfplugin6.Provider.InvokeAction:output_type -> tfplugin6.InvokeAction.Event + 155, // 248: tfplugin6.Provider.ValidateActionConfig:output_type -> tfplugin6.ValidateActionConfig.Response + 56, // 249: tfplugin6.Provider.StopProvider:output_type -> tfplugin6.StopProvider.Response + 217, // [217:250] is the sub-list for method output_type + 184, // [184:217] is the sub-list for method input_type + 184, // [184:184] is the sub-list for extension type_name + 184, // [184:184] is the sub-list for extension extendee + 0, // [0:184] is the sub-list for field type_name } func init() { file_tfplugin6_proto_init() } @@ -8758,17 +9162,17 @@ func file_tfplugin6_proto_init() { (*ActionSchema_Lifecycle_)(nil), (*ActionSchema_Linked_)(nil), } - file_tfplugin6_proto_msgTypes[45].OneofWrappers = []any{ + file_tfplugin6_proto_msgTypes[48].OneofWrappers = []any{ (*AttributePath_Step_AttributeName)(nil), (*AttributePath_Step_ElementKeyString)(nil), (*AttributePath_Step_ElementKeyInt)(nil), } - file_tfplugin6_proto_msgTypes[109].OneofWrappers = []any{} - file_tfplugin6_proto_msgTypes[110].OneofWrappers = []any{} - file_tfplugin6_proto_msgTypes[111].OneofWrappers = []any{} file_tfplugin6_proto_msgTypes[112].OneofWrappers = []any{} - file_tfplugin6_proto_msgTypes[120].OneofWrappers = []any{} - file_tfplugin6_proto_msgTypes[136].OneofWrappers = []any{ + file_tfplugin6_proto_msgTypes[113].OneofWrappers = []any{} + file_tfplugin6_proto_msgTypes[114].OneofWrappers = []any{} + file_tfplugin6_proto_msgTypes[115].OneofWrappers = []any{} + file_tfplugin6_proto_msgTypes[123].OneofWrappers = []any{} + file_tfplugin6_proto_msgTypes[143].OneofWrappers = []any{ (*InvokeAction_Event_Progress_)(nil), (*InvokeAction_Event_Completed_)(nil), } @@ -8778,7 +9182,7 @@ func file_tfplugin6_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_tfplugin6_proto_rawDesc), len(file_tfplugin6_proto_rawDesc)), NumEnums: 6, - NumMessages: 143, + NumMessages: 150, NumExtensions: 0, NumServices: 1, }, @@ -8848,6 +9252,10 @@ type ProviderClient interface { ValidateStateStoreConfig(ctx context.Context, in *ValidateStateStore_Request, opts ...grpc.CallOption) (*ValidateStateStore_Response, error) // ConfigureStateStore configures the state store, such as S3 connection in the context of already configured provider ConfigureStateStore(ctx context.Context, in *ConfigureStateStore_Request, opts ...grpc.CallOption) (*ConfigureStateStore_Response, error) + // ReadStateBytes streams byte chunks of a given state file from a state store + ReadStateBytes(ctx context.Context, in *ReadStateBytes_Request, opts ...grpc.CallOption) (Provider_ReadStateBytesClient, error) + // WriteStateBytes streams byte chunks of a given state file into a state store + WriteStateBytes(ctx context.Context, opts ...grpc.CallOption) (Provider_WriteStateBytesClient, error) // GetStates returns a list of all states (i.e. CE workspaces) managed by a given state store GetStates(ctx context.Context, in *GetStates_Request, opts ...grpc.CallOption) (*GetStates_Response, error) // DeleteState instructs a given state store to delete a specific state (i.e. a CE workspace) @@ -9116,6 +9524,72 @@ func (c *providerClient) ConfigureStateStore(ctx context.Context, in *ConfigureS return out, nil } +func (c *providerClient) ReadStateBytes(ctx context.Context, in *ReadStateBytes_Request, opts ...grpc.CallOption) (Provider_ReadStateBytesClient, error) { + stream, err := c.cc.NewStream(ctx, &_Provider_serviceDesc.Streams[1], "/tfplugin6.Provider/ReadStateBytes", opts...) + if err != nil { + return nil, err + } + x := &providerReadStateBytesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Provider_ReadStateBytesClient interface { + Recv() (*ReadStateBytes_Response, error) + grpc.ClientStream +} + +type providerReadStateBytesClient struct { + grpc.ClientStream +} + +func (x *providerReadStateBytesClient) Recv() (*ReadStateBytes_Response, error) { + m := new(ReadStateBytes_Response) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *providerClient) WriteStateBytes(ctx context.Context, opts ...grpc.CallOption) (Provider_WriteStateBytesClient, error) { + stream, err := c.cc.NewStream(ctx, &_Provider_serviceDesc.Streams[2], "/tfplugin6.Provider/WriteStateBytes", opts...) + if err != nil { + return nil, err + } + x := &providerWriteStateBytesClient{stream} + return x, nil +} + +type Provider_WriteStateBytesClient interface { + Send(*WriteStateBytes_RequestChunk) error + CloseAndRecv() (*WriteStateBytes_Response, error) + grpc.ClientStream +} + +type providerWriteStateBytesClient struct { + grpc.ClientStream +} + +func (x *providerWriteStateBytesClient) Send(m *WriteStateBytes_RequestChunk) error { + return x.ClientStream.SendMsg(m) +} + +func (x *providerWriteStateBytesClient) CloseAndRecv() (*WriteStateBytes_Response, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(WriteStateBytes_Response) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *providerClient) GetStates(ctx context.Context, in *GetStates_Request, opts ...grpc.CallOption) (*GetStates_Response, error) { out := new(GetStates_Response) err := c.cc.Invoke(ctx, "/tfplugin6.Provider/GetStates", in, out, opts...) @@ -9144,7 +9618,7 @@ func (c *providerClient) PlanAction(ctx context.Context, in *PlanAction_Request, } func (c *providerClient) InvokeAction(ctx context.Context, in *InvokeAction_Request, opts ...grpc.CallOption) (Provider_InvokeActionClient, error) { - stream, err := c.cc.NewStream(ctx, &_Provider_serviceDesc.Streams[1], "/tfplugin6.Provider/InvokeAction", opts...) + stream, err := c.cc.NewStream(ctx, &_Provider_serviceDesc.Streams[3], "/tfplugin6.Provider/InvokeAction", opts...) if err != nil { return nil, err } @@ -9239,6 +9713,10 @@ type ProviderServer interface { ValidateStateStoreConfig(context.Context, *ValidateStateStore_Request) (*ValidateStateStore_Response, error) // ConfigureStateStore configures the state store, such as S3 connection in the context of already configured provider ConfigureStateStore(context.Context, *ConfigureStateStore_Request) (*ConfigureStateStore_Response, error) + // ReadStateBytes streams byte chunks of a given state file from a state store + ReadStateBytes(*ReadStateBytes_Request, Provider_ReadStateBytesServer) error + // WriteStateBytes streams byte chunks of a given state file into a state store + WriteStateBytes(Provider_WriteStateBytesServer) error // GetStates returns a list of all states (i.e. CE workspaces) managed by a given state store GetStates(context.Context, *GetStates_Request) (*GetStates_Response, error) // DeleteState instructs a given state store to delete a specific state (i.e. a CE workspace) @@ -9330,6 +9808,12 @@ func (*UnimplementedProviderServer) ValidateStateStoreConfig(context.Context, *V func (*UnimplementedProviderServer) ConfigureStateStore(context.Context, *ConfigureStateStore_Request) (*ConfigureStateStore_Response, error) { return nil, status.Errorf(codes.Unimplemented, "method ConfigureStateStore not implemented") } +func (*UnimplementedProviderServer) ReadStateBytes(*ReadStateBytes_Request, Provider_ReadStateBytesServer) error { + return status.Errorf(codes.Unimplemented, "method ReadStateBytes not implemented") +} +func (*UnimplementedProviderServer) WriteStateBytes(Provider_WriteStateBytesServer) error { + return status.Errorf(codes.Unimplemented, "method WriteStateBytes not implemented") +} func (*UnimplementedProviderServer) GetStates(context.Context, *GetStates_Request) (*GetStates_Response, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStates not implemented") } @@ -9806,6 +10290,53 @@ func _Provider_ConfigureStateStore_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _Provider_ReadStateBytes_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ReadStateBytes_Request) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ProviderServer).ReadStateBytes(m, &providerReadStateBytesServer{stream}) +} + +type Provider_ReadStateBytesServer interface { + Send(*ReadStateBytes_Response) error + grpc.ServerStream +} + +type providerReadStateBytesServer struct { + grpc.ServerStream +} + +func (x *providerReadStateBytesServer) Send(m *ReadStateBytes_Response) error { + return x.ServerStream.SendMsg(m) +} + +func _Provider_WriteStateBytes_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ProviderServer).WriteStateBytes(&providerWriteStateBytesServer{stream}) +} + +type Provider_WriteStateBytesServer interface { + SendAndClose(*WriteStateBytes_Response) error + Recv() (*WriteStateBytes_RequestChunk, error) + grpc.ServerStream +} + +type providerWriteStateBytesServer struct { + grpc.ServerStream +} + +func (x *providerWriteStateBytesServer) SendAndClose(m *WriteStateBytes_Response) error { + return x.ServerStream.SendMsg(m) +} + +func (x *providerWriteStateBytesServer) Recv() (*WriteStateBytes_RequestChunk, error) { + m := new(WriteStateBytes_RequestChunk) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func _Provider_GetStates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetStates_Request) if err := dec(in); err != nil { @@ -10044,6 +10575,16 @@ var _Provider_serviceDesc = grpc.ServiceDesc{ Handler: _Provider_ListResource_Handler, ServerStreams: true, }, + { + StreamName: "ReadStateBytes", + Handler: _Provider_ReadStateBytes_Handler, + ServerStreams: true, + }, + { + StreamName: "WriteStateBytes", + Handler: _Provider_WriteStateBytes_Handler, + ClientStreams: true, + }, { StreamName: "InvokeAction", Handler: _Provider_InvokeAction_Handler,