Skip to content

PSS: Add alternative, experimental version of init command that downloads providers in two stages#37350

Merged
SarahFrench merged 33 commits intomainfrom
pss/multistage-provider-download-experiment
Aug 18, 2025
Merged

PSS: Add alternative, experimental version of init command that downloads providers in two stages#37350
SarahFrench merged 33 commits intomainfrom
pss/multistage-provider-download-experiment

Conversation

@SarahFrench
Copy link
Copy Markdown
Member

@SarahFrench SarahFrench commented Jul 18, 2025

Description

This PR introduces an alternative version of the logic controlling events during an init command. Instead of downloading providers in a single step, the new logic downloads providers in two steps:

  • Providers described in the configuration.
  • Providers described in the state.

The dependency locks identified after each provider download action are tracked. The locks identified from the config are used as an input for downloading providers present in the state, and this prevents providers being re-downloaded or another version of a provider being downloaded. The locks identified from the config and the state are later combined and written to the dependency lock file.

This PR also changes how we control the parsing of the state_store block to gate this feature as experimental. The old approach (implemented here) is not compatible with multiple tests running in parallel, so this commit changes the way the feature is gated.

Details

The original version of the init logic (internal/command/init_run.go) roughly does this:

  • Loads the root module's configuration
  • Uses that config to initialise the backend
  • Reads the state using that backend
  • Loads the complete configuration (incl. child modules)
  • Makes a call to the getProviders method, with the full config and state data as inputs to that process.
    • This downloads providers and updates the dependency lock file.

In the new version (internal/command/init_run_experiment.go) there are these changes:

  • Load the complete configuration
  • Download providers described by the config using getProvidersFromConfig (step1)
  • Initialise the backend (which may depend on a provider in the context of PSS)
  • Read in the state
  • Download any remaining needed providers using getProvidersFromState (step2)
  • Update the dependency lock file using the combination of locks identified from step 1 and 2.

The original version of this logic is used by default. The new init logic is only used when Terraform has experiments enabled and either the -enable-pluggable-state-storage-experiment flag is passed to the init command or an environment variable called TF_ENABLE_PLUGGABLE_STATE_STORAGE has a non-empty value.

Target Release

N/A

Rollback Plan

  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.

CHANGELOG entry

  • This change is user-facing and I added a changelog entry.
  • This change is not user-facing.

@SarahFrench SarahFrench added the no-changelog-needed Add this to your PR if the change does not require a changelog entry label Jul 18, 2025
Base automatically changed from pss/multistage-provider-download-prep to main July 30, 2025 18:11
@SarahFrench SarahFrench force-pushed the pss/multistage-provider-download-experiment branch from 35e5fd6 to e4e4587 Compare July 31, 2025 10:00
@SarahFrench SarahFrench force-pushed the pss/multistage-provider-download-experiment branch from 23f73b1 to e089961 Compare August 6, 2025 17:06
@SarahFrench
Copy link
Copy Markdown
Member Author

SarahFrench commented Aug 8, 2025

TestInit_stateStoreBlockIsExperimental is passing when run in isolation, but is failing when run in parallel to other tests. Looking into why that's the case...

Edit: it's due to the modification of the package level terraformBlockSchema variable. 🤦🏻 - this is fine for gating the feature for real users, but means test can interfere with each other.

@SarahFrench SarahFrench force-pushed the pss/multistage-provider-download-experiment branch from 216359a to 764650f Compare August 11, 2025 08:09
@SarahFrench SarahFrench force-pushed the pss/multistage-provider-download-experiment branch from 764650f to 4ad9f59 Compare August 11, 2025 09:14
@SarahFrench SarahFrench changed the title [DNM/WIP] PSS: multistage provider download experiment PSS: Add alternative, experimental version of init command that downloads providers in two stages Aug 11, 2025
@SarahFrench SarahFrench marked this pull request as ready for review August 11, 2025 11:01
@SarahFrench SarahFrench requested a review from a team as a code owner August 11, 2025 11:01
@SarahFrench SarahFrench requested a review from radeksimko August 11, 2025 11:01
…ocks and merge those with any locks on file. This allows re-use of providers downloaded by `getProvidersFromConfig` in the same init command
…provider download step.

When downloading providers described only in the state then the provider may already be downloaded from a previous init (i.e. is recorded in the deps lock file) or downloaded during step 1 of provider download. The message here needs to cover both potential scenarios.
@SarahFrench SarahFrench force-pushed the pss/multistage-provider-download-experiment branch from 626d03f to 31f2cc1 Compare August 14, 2025 09:50
@SarahFrench SarahFrench requested a review from radeksimko August 14, 2025 09:58
@SarahFrench SarahFrench merged commit da76dba into main Aug 18, 2025
7 checks passed
@SarahFrench SarahFrench deleted the pss/multistage-provider-download-experiment branch August 18, 2025 10:20
SarahFrench added a commit that referenced this pull request Aug 26, 2025
…nloads providers in two stages (#37350)

* Add forked version of `run` logic that's only used if experiments are enabled

* Reorder actions in experimental init - load in full config before configuring the backend.

* Add getProvidersFromConfig method, initially as an exact copy of getProviders

* Make getProvidersFromConfig not use state to get providers

* Add `appendLockedDependencies` method to `Meta` to allow multi-phase saving to the dep locks file

* Update experimental init to use new getProvidersFromConfig method

* Add new getProvidersFromState method that only accepts state information as input for getting providers. Use in experimental init and append values to existing deps lock file

* Update messages sent to view about provider download phases

* Change init to save updates to the deps lock file only once

* Make Terraform output report that a lock file _will_ be made after providers are determined from config

* Remove use of `ProviderDownloadOutcome`s

* Move repeated code into separate method

* Change provider download approach: determine if locks changed at point of attempting to update the lockfile, keep record of incomplete providers inside init command struct

* Refactor `mergeLockedDependencies` and update test

* Add comments to provider download methods

* Fix issue where incorrect message ouput to view when downloading providers

* Update `mergeLockedDependencies` method to be more generic

* Update `getProvidersFromState` method to receive in-progress config locks and merge those with any locks on file. This allows re-use of providers downloaded by `getProvidersFromConfig` in the same init command

* Fix config for `TestInit_stateStoreBlockIsExperimental`

* Improve testing of mergeLockedDependencies; state locks are always missing version constraints

* Add tests for 2 phase provider download

* Add test case to cover use of the `-upgrade` flag

* Change the message shown when a provider is reused during the second provider download step.

When downloading providers described only in the state then the provider may already be downloaded from a previous init (i.e. is recorded in the deps lock file) or downloaded during step 1 of provider download. The message here needs to cover both potential scenarios.

* Update mergeLockedDependencies comment

* fix: completely remove use of upgrade flag in getProvidersFromState

* Fix: avoid nil pointer errors by returning an empty collection of locks when there is no state

* Fix: use state store data only in diagnostic

* Change how we make PSS experimental - avoid relying on a package level variable that causes tests to interact.

* Remove full-stop in view message, update tests

* Update span names to be unique

* Re-add lost early returns

* Remove unused view messages

* Add comments to new view messages
@github-actions
Copy link
Copy Markdown
Contributor

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

no-changelog-needed Add this to your PR if the change does not require a changelog entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants