Skip to content

provisioner/powershell: recreate env var reader on each upload retry - #13735

Open
patrix87 wants to merge 1 commit into
hashicorp:mainfrom
patrix87:f-powershell-envvar-retry
Open

patrix87 wants to merge 1 commit into
hashicorp:mainfrom
patrix87:f-powershell-envvar-retry

Conversation

@patrix87

Copy link
Copy Markdown

Description

The PowerShell provisioner uploads the env var file (remote_env_var_path) inside a retry loop, but it created the strings.Reader for that upload once, before the loop. If an Upload attempt failed after reading part or all of the reader, the retry sent only what was left: a truncated or empty file. The retry then reported success. The script dot-sourced the empty file without error and ran with no environment_vars set, then failed later with an unrelated-looking null-argument error.

With WinRM this is not only theoretical: winrmcp reads the whole input before its restore and temp-file cleanup steps. A transient failure in either step fails the Upload with the reader already at EOF, and the retry writes an empty destination file.

This PR creates the reader inside the retry closure, so every attempt uploads the full text. This matches the script upload in the same file (f.Seek(0, 0) on each attempt) and the shell provisioner's env var file upload. Nothing else changes.

I checked the other uploads on these paths:

  • The elevated_user path also goes through prepareEnvVars → uploadEnvVars, so this fix covers it.
  • guestexec.GenerateElevatedRunner in packer-plugin-sdk does one Upload with no retry, so it is not affected.
  • The remote cleanup script already builds a new reader inside its retry closure.

Tests

TestProvision_uploadEnvVarsRetry uses a mock communicator whose first Upload reads some bytes (one case) or all bytes (another case) and then returns an error. The test checks that the second Upload receives the full env var text. Both cases fail without the fix: the retry sends the unread tail in the first case and an empty string in the second. Both pass with the fix.

go test ./provisioner/... -count=1   # ok
go vet ./provisioner/powershell/     # clean
gofmt -l provisioner/powershell/     # clean

Backward compatibility: no config or template changes. The only change in behavior is that a retried env var upload now writes the full file.

Resolved Issues

Closes #13734

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

None. No changes to access controls, encryption, or logging.

The env var file upload reused a single strings.Reader across retry
attempts. When an attempt failed after the communicator had read some
or all of it (e.g. a transient WinRM error during winrmcp's restore or
cleanup step), the retry uploaded a truncated or empty file and
reported success, so the next script ran without its environment_vars.

Create the reader inside the retry closure so every attempt uploads the
full content, matching the script upload which rewinds its file.
@patrix87
patrix87 requested a review from a team as a code owner October 29, 2026 20:37
@hashicorp-cla-app

hashicorp-cla-app Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PowerShell provisioner: retrying the env-var upload sends an empty file, so scripts run without environment_vars

1 participant