hashicorp / packer

Packer is a tool for creating identical machine images for multiple platforms from a single source configuration.
http://www.packer.io
Other
14.98k stars 3.33k forks source link

Add pwsh provisioner to linux #12429

Open jachin84 opened 1 year ago

jachin84 commented 1 year ago

Community Note

Please search the existing issues for relevant feature requests, and use the reaction feature (https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to add upvotes to pre-existing requests.

Description

Add support for using the powershell provisioner on linux. I'm currently using the standard shell provisioner and changing the run command like so:

provisioner "shell" {
    execute_command  = "sudo sh -c '{{ .Vars }} pwsh -f {{ .Path }}'"
    scripts          = ["${path.root}/scripts/Install-stuff.ps1"]
  }

This doesn't seem to work when specifying inline.

Use Case(s)

When building linux images using pwsh as the primary scripting language instead of bash.

Potential configuration

I'd love it if something like this worked:

provisioner "pwsh" {
    inline          = [ "Write-Host \"Hello from PowerShell\""]
}
tenthirtyam commented 2 weeks ago

Did you happen to try use_pwsh = true with the provisioner?

Although, if that works the docs should be updated to note that it's pwsh for cross platform and remove the .exe reference.

Ryan

cc @lbajolet-hashicorp

lbajolet-hashicorp commented 2 weeks ago

Hey @tenthirtyam,

Thanks for the update here. I believe the intent of the Powershell provisioner is mostly for users building Windows VMs (as the first sentence of the provisioner hints: "The PowerShell Packer provisioner runs PowerShell scripts on Windows machines"), though that is essentially cross-platform now that pwsh is built for Linux and macOS these days.

I've never tried running pwsh on Linux guests tbf, not even sure if the option will work on non-Windows machines, but it very well might. If possible @jachin84 could you update us on using this option in that context? If it persists in not calling the shell you're expecting, we can probably fix that, otherwise as Ryan said, we can update the docs to lessen the dependency on Windows in there.

Thanks!

jachin84 commented 2 weeks ago

I tried the use_pwsh = true

provisioner "powershell" {
    use_pwsh = true
    environment_vars = ["HELPER_SCRIPTS=${var.helper_script_folder}", "INSTALLER_SCRIPT_FOLDER=${var.installer_script_folder}"]
    scripts          = ["${path.root}/../scripts/build/Install-PowerShellModules.ps1", "${path.root}/../scripts/build/Install-PowerShellAzModules.ps1"]
  }

This gives me an error:

==> azure-arm.build_image: Provisioning with powershell script: S:/Kallipr/runner-images/images/linux/templates/../scripts/build/Install-PowerShellModules.ps1
==> azure-arm.build_image: Error processing command: Error uploading ps script containing env vars: scp: c:/Windows/Temp: No such file or directory

Looking at that log (c:/Windows/Temp) it looks like it is assuming windows when using the powershell provisioner.

My scenario, which is probably not common, is building a Linux guest but using PowerShell core scripts to customize the guest rather than bash. As I mentioned the workaround is something like:

  provisioner "shell" {
    environment_vars = ["HELPER_SCRIPTS=${var.helper_script_folder}", "INSTALLER_SCRIPT_FOLDER=${var.installer_script_folder}"]
    execute_command  = "sudo sh -c '{{ .Vars }} pwsh -f {{ .Path }}'"
    scripts          = ["${path.root}/../scripts/build/Install-PowerShellModules.ps1", "${path.root}/../scripts/build/Install-PowerShellAzModules.ps1"]
  }

It would be nice if this was handled by default as I often forget to add execute_command = "sudo sh -c '{{ .Vars }} pwsh -f {{ .Path }}'" to the shell provisioner.

Maybe it would be easier to add a use_pwsh = true option to the shell provisioner?

tenthirtyam commented 2 weeks ago

@lbajolet-hashicorp feel free to assign to me and I'll work on this one.

lbajolet-hashicorp commented 2 weeks ago

Thanks for the experiment and reporting back @jachin84, much appreciated!

Yeah, the fact that the powershell provisioner assumes Windows doesn't surprise me, not a lot of people use it on other platforms, and assuming Windows enables us to perform some boilerplate actions that are OS-specific without having to specify everything manually. This approach may need to be revisited at some point though, but for now we'll make do with what we have.

Regarding a use_pwsh attribute to the shell provisioner, I'm not certain this is a good idea. My main gripe with this is that if we start having use_.* for shell, we'll be tempted to add more and more variants (e.g. use_zsh, use_fish, use_powershell, etc.). Additionally, I imagine use_pwsh has more implications than changing execute_command, we'd need to check that.

Not sure what'd be best for handling this as idiomatically as possible. I'll bring this up for discussion internally and we'll pop back here later to address this issue.

Thanks again to the both of you!