diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index 9e762ea183f..b3d44ffa379 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -88,6 +88,9 @@ type Config struct { // ``` DebugMode int `mapstructure:"debug_mode"` + // A duration of how long to pause after the provisioner + PauseAfter time.Duration `mapstructure:"pause_after"` + ctx interpolate.Context } @@ -351,6 +354,11 @@ func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packe log.Printf("remote cleanup script failed to upload; skipping the removal of temporary files: %s; ", strings.Join(uploadedScripts, ",")) } + if p.config.PauseAfter != 0 { + ui.Say(fmt.Sprintf("Pausing %s after this provisioner...", p.config.PauseAfter)) + time.Sleep(p.config.PauseAfter) + } + return nil } diff --git a/provisioner/powershell/provisioner.hcl2spec.go b/provisioner/powershell/provisioner.hcl2spec.go index cbeb427ce74..04109019e06 100644 --- a/provisioner/powershell/provisioner.hcl2spec.go +++ b/provisioner/powershell/provisioner.hcl2spec.go @@ -37,6 +37,7 @@ type FlatConfig struct { ElevatedPassword *string `mapstructure:"elevated_password" cty:"elevated_password" hcl:"elevated_password"` ExecutionPolicy *string `mapstructure:"execution_policy" cty:"execution_policy" hcl:"execution_policy"` DebugMode *int `mapstructure:"debug_mode" cty:"debug_mode" hcl:"debug_mode"` + PauseAfter *string `mapstructure:"pause_after" cty:"pause_after" hcl:"pause_after"` } // FlatMapstructure returns a new FlatConfig. @@ -78,6 +79,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "elevated_password": &hcldec.AttrSpec{Name: "elevated_password", Type: cty.String, Required: false}, "execution_policy": &hcldec.AttrSpec{Name: "execution_policy", Type: cty.String, Required: false}, "debug_mode": &hcldec.AttrSpec{Name: "debug_mode", Type: cty.Number, Required: false}, + "pause_after": &hcldec.AttrSpec{Name: "pause_after", Type: cty.String, Required: false}, } return s } diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index 65cbbe8970c..515c85ff8ca 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -381,6 +381,42 @@ func TestProvisionerProvision_ValidExitCodes(t *testing.T) { } } +func TestProvisionerProvision_PauseAfter(t *testing.T) { + config := testConfig() + delete(config, "inline") + + // Defaults provided by Packer + config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1" + config["inline"] = []string{"whoami"} + ui := testUi() + p := new(Provisioner) + + // Defaults provided by Packer + p.config.PackerBuildName = "vmware" + p.config.PackerBuilderType = "iso" + p.config.ValidExitCodes = []int{0, 200} + pause_amount := time.Second + p.config.PauseAfter = pause_amount + comm := new(packersdk.MockCommunicator) + comm.StartExitStatus = 200 + err := p.Prepare(config) + if err != nil { + t.Fatalf("Prepar failed: %s", err) + } + + start_time := time.Now() + err = p.Provision(context.Background(), ui, comm, generatedData()) + end_time := time.Now() + + if err != nil { + t.Fatal("should not have error") + } + + if end_time.Sub(start_time) < pause_amount { + t.Fatal("Didn't wait pause_amount") + } +} + func TestProvisionerProvision_InvalidExitCodes(t *testing.T) { config := testConfig() delete(config, "inline") diff --git a/website/content/docs/provisioners/powershell.mdx b/website/content/docs/provisioners/powershell.mdx index f0402121b9b..5120a7d0b0e 100644 --- a/website/content/docs/provisioners/powershell.mdx +++ b/website/content/docs/provisioners/powershell.mdx @@ -244,6 +244,9 @@ provisioner "powershell" { exists in order to deal with times when SSH may restart, such as a system reboot. Set this to a higher value if reboots take a longer amount of time. +- `pause_after` (string) - Wait the amount of time after provisioning a powershell + script, this pause be taken if all previous steps were successful. + @include 'provisioners/common-config.mdx' ## Default Environmental Variables