diff --git a/builder/amazon/ebs/acceptance/builder_acceptance.go b/builder/amazon/ebs/acceptance/builder_acceptance.go index 0b79e4382..93fa5d9ac 100644 --- a/builder/amazon/ebs/acceptance/builder_acceptance.go +++ b/builder/amazon/ebs/acceptance/builder_acceptance.go @@ -18,18 +18,31 @@ import ( type AmazonEBSAccTest struct{} func (s *AmazonEBSAccTest) GetConfigs() (map[string]string, error) { - filePath := filepath.Join("../../builder/amazon/ebs/acceptance/test-fixtures/", "amazon-ebs.txt") - config, err := os.Open(filePath) - if err != nil { - return nil, fmt.Errorf("Expected to find %s", filePath) + fixtures := map[string]string{ + "linux": "amazon-ebs.txt", + "windows": "amazon-ebs_windows.txt", } - defer config.Close() - file, err := ioutil.ReadAll(config) - if err != nil { - return nil, fmt.Errorf("Uneble to read %s", filePath) + configs := make(map[string]string) + + for distro, fixture := range fixtures { + fileName := fixture + filePath := filepath.Join("../../builder/amazon/ebs/acceptance/test-fixtures/", fileName) + config, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("Expected to find %s", filePath) + } + defer config.Close() + + file, err := ioutil.ReadAll(config) + if err != nil { + return nil, fmt.Errorf("Unable to read %s", filePath) + } + + configs[distro] = string(file) + } - return map[string]string{"linux": string(file)}, nil + return configs, nil } func (s *AmazonEBSAccTest) CleanUp() error { diff --git a/builder/amazon/ebs/acceptance/test-fixtures/amazon-ebs_windows.txt b/builder/amazon/ebs/acceptance/test-fixtures/amazon-ebs_windows.txt new file mode 100644 index 000000000..b23dc04ba --- /dev/null +++ b/builder/amazon/ebs/acceptance/test-fixtures/amazon-ebs_windows.txt @@ -0,0 +1,23 @@ +{ + "type": "amazon-ebs", + "region": "us-east-1", + "instance_type": "t2.micro", + "source_ami_filter": { + "filters": { + "virtualization-type": "hvm", + "name": "*Windows_Server-2012-R2*English-64Bit-Base*", + "root-device-type": "ebs" + }, + "most_recent": true, + "owners": "amazon" + }, + "ami_name": "packer-acc-test", + "user_data_file": "../../builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt", + "communicator": "winrm", + "winrm_username": "Administrator", + "winrm_password": "SuperS3cr3t!!!!", + "force_deregister" : true, + "tags": { + "packer-test": "true" + } +} diff --git a/builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt b/builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt new file mode 100644 index 000000000..8229c8842 --- /dev/null +++ b/builder/amazon/ebs/acceptance/test-fixtures/scripts/bootstrap_win.txt @@ -0,0 +1,40 @@ + +# Set administrator password +net user Administrator SuperS3cr3t!!!! +wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE + +# First, make sure WinRM can't be connected to +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block + +# Delete any existing WinRM listeners +winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null +winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null + +# Disable group policies which block basic authentication and unencrypted login + +Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowBasic -Value 1 +Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Client -Name AllowUnencryptedTraffic -Value 1 +Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowBasic -Value 1 +Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WinRM\Service -Name AllowUnencryptedTraffic -Value 1 + + +# Create a new WinRM listener and configure +winrm create winrm/config/listener?Address=*+Transport=HTTP +winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}' +winrm set winrm/config '@{MaxTimeoutms="7200000"}' +winrm set winrm/config/service '@{AllowUnencrypted="true"}' +winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}' +winrm set winrm/config/service/auth '@{Basic="true"}' +winrm set winrm/config/client/auth '@{Basic="true"}' + +# Configure UAC to allow privilege elevation in remote shells +$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' +$Setting = 'LocalAccountTokenFilterPolicy' +Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force + +# Configure and restart the WinRM Service; Enable the required firewall exception +Stop-Service -Name WinRM +Set-Service -Name WinRM -StartupType Automatic +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any +Start-Service -Name WinRM + diff --git a/provisioner/powershell/provisioner_acc_test.go b/provisioner/powershell/provisioner_acc_test.go new file mode 100644 index 000000000..520136b21 --- /dev/null +++ b/provisioner/powershell/provisioner_acc_test.go @@ -0,0 +1,86 @@ +package powershell_test + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/packer/command" + "github.com/hashicorp/packer/helper/tests/acc" + "github.com/hashicorp/packer/packer" +) + +func TestPowershellProvisioner_Inline(t *testing.T) { + p := os.Getenv("ACC_TEST_PROVISIONERS") + if p != "all" && !strings.Contains(p, "powershell") { + t.Skip() + } + + testProvisioner := PowershellProvisionerAccTest{"powershell-inline-provisioner.txt"} + acc.TestProvisionersAgainstBuilders(&testProvisioner, t) +} + +func TestPowershellProvisioner_Script(t *testing.T) { + p := os.Getenv("ACC_TEST_PROVISIONERS") + if p != "all" && !strings.Contains(p, "powershell") { + t.Skip() + } + + testProvisioner := PowershellProvisionerAccTest{"powershell-script-provisioner.txt"} + acc.TestProvisionersAgainstBuilders(&testProvisioner, t) +} + +type PowershellProvisionerAccTest struct { + ConfigName string +} + +func (s *PowershellProvisionerAccTest) GetName() string { + return "powershell" +} + +func (s *PowershellProvisionerAccTest) GetConfig() (string, error) { + filePath := filepath.Join("./test-fixtures", s.ConfigName) + config, err := os.Open(filePath) + if err != nil { + return "", fmt.Errorf("Expected to find %s", filePath) + } + defer config.Close() + + file, err := ioutil.ReadAll(config) + return string(file), nil +} + +func (s *PowershellProvisionerAccTest) GetProvisionerStore() packer.MapOfProvisioner { + return packer.MapOfProvisioner{ + "powershell": func() (packer.Provisioner, error) { return command.Provisioners["powershell"], nil }, + } +} + +func (s *PowershellProvisionerAccTest) IsCompatible(builder string, vmOS string) bool { + return vmOS == "windows" +} + +func (s *PowershellProvisionerAccTest) RunTest(c *command.BuildCommand, args []string) error { + UUID := os.Getenv("PACKER_RUN_UUID") + if UUID == "" { + UUID, _ = uuid.GenerateUUID() + os.Setenv("PACKER_RUN_UUID", UUID) + } + + if code := c.Run(args); code != 0 { + ui := c.Meta.Ui.(*packer.BasicUi) + out := ui.Writer.(*bytes.Buffer) + err := ui.ErrorWriter.(*bytes.Buffer) + return fmt.Errorf( + "Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s", + out.String(), + err.String()) + } + + return nil +} diff --git a/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt b/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt new file mode 100644 index 000000000..1b63c1742 --- /dev/null +++ b/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt @@ -0,0 +1,8 @@ +{ + "type": "powershell", + "environment_vars": "PackerRunUUID={{build `PackerRunUUID`}},ID={{build `ID`}}", + "inline": [ + "Write-Host \"$env:ID for provisioner.$env:PackerRunUUID\"" + ] +} + diff --git a/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt b/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt new file mode 100644 index 000000000..f0fc663e1 --- /dev/null +++ b/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt @@ -0,0 +1,11 @@ +{ + "type": "powershell", + "script": "../../provisioner/powershell/test-fixtures/scripts/sample_script.ps1", + "environment_vars": [ + "VAR1=A$Dollar", + "VAR2=A`Backtick", + "VAR3=A'SingleQuote", + "VAR4=A\"DoubleQuote" + ] +} + diff --git a/provisioner/powershell/test-fixtures/scripts/sample_script.ps1 b/provisioner/powershell/test-fixtures/scripts/sample_script.ps1 new file mode 100644 index 000000000..0c146c9bd --- /dev/null +++ b/provisioner/powershell/test-fixtures/scripts/sample_script.ps1 @@ -0,0 +1,5 @@ +write-output("packer_build_name is automatically set for you, or you can set it in your builder variables; the default for this builder is: " + $env:packer_build_name ) +write-output("remember that escaping variables in powershell requires backticks; for example var1 from our config is " + $env:var1 ) +write-output("likewise, var2 is " + $env:var2 ) +write-output("and var3 is " + $env:var3 ) +