394 lines
9.8 KiB
Go
394 lines
9.8 KiB
Go
|
package puppet
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/hashicorp/terraform/communicator"
|
||
|
"github.com/hashicorp/terraform/communicator/remote"
|
||
|
"github.com/hashicorp/terraform/helper/schema"
|
||
|
"github.com/hashicorp/terraform/terraform"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
getHostByNameCmd = `powershell -Command "& {([System.Net.Dns]::GetHostByName(($env:computerName))).Hostname}"`
|
||
|
domainQueryCmd = `powershell -Command "& {(Get-WmiObject -Query 'select DNSDomain from Win32_NetworkAdapterConfiguration where IPEnabled = True').DNSDomain}"`
|
||
|
downloadInstallerCmd = `powershell -Command "& {[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}; (New-Object System.Net.WebClient).DownloadFile('https://puppet.test.com:8140/packages/current/install.ps1', 'install.ps1')}"`
|
||
|
runInstallerCmd = `powershell -Command "& .\install.ps1 -PuppetServiceEnsure stopped"`
|
||
|
runPuppetCmd = "puppet agent --test --server puppet.test.com --environment production"
|
||
|
)
|
||
|
|
||
|
func TestResourceProvisioner_windowsUploadFile(t *testing.T) {
|
||
|
cases := map[string]struct {
|
||
|
Config map[string]interface{}
|
||
|
Commands map[string]bool
|
||
|
CommandFunc func(*remote.Cmd) error
|
||
|
ExpectedError bool
|
||
|
Uploads map[string]string
|
||
|
File io.Reader
|
||
|
Dir string
|
||
|
Filename string
|
||
|
}{
|
||
|
"Successful upload": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
Commands: map[string]bool{
|
||
|
`powershell.exe new-item -itemtype directory -force -path C:\ProgramData\PuppetLabs\puppet\etc`: true,
|
||
|
},
|
||
|
Uploads: map[string]string{
|
||
|
`C:\ProgramData\PuppetLabs\puppet\etc\csr_attributes.yaml`: "",
|
||
|
},
|
||
|
Dir: `C:\ProgramData\PuppetLabs\puppet\etc`,
|
||
|
Filename: "csr_attributes.yaml",
|
||
|
File: strings.NewReader(""),
|
||
|
},
|
||
|
"Failure when creating the directory": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
Commands: map[string]bool{
|
||
|
`powershell.exe new-item -itemtype directory -force -path C:\ProgramData\PuppetLabs\puppet\etc`: true,
|
||
|
},
|
||
|
Dir: `C:\ProgramData\PuppetLabs\puppet\etc`,
|
||
|
Filename: "csr_attributes.yaml",
|
||
|
File: strings.NewReader(""),
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: `powershell.exe new-item -itemtype directory -force -path C:\ProgramData\PuppetLabs\puppet\etc`,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for k, tc := range cases {
|
||
|
p, err := decodeConfig(
|
||
|
schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Error: %v", err)
|
||
|
}
|
||
|
|
||
|
c := new(communicator.MockCommunicator)
|
||
|
c.Commands = tc.Commands
|
||
|
c.Uploads = tc.Uploads
|
||
|
if tc.CommandFunc != nil {
|
||
|
c.CommandFunc = tc.CommandFunc
|
||
|
}
|
||
|
p.comm = c
|
||
|
p.output = new(terraform.MockUIOutput)
|
||
|
|
||
|
err = p.windowsUploadFile(tc.File, tc.Dir, tc.Filename)
|
||
|
if tc.ExpectedError {
|
||
|
if err == nil {
|
||
|
t.Fatalf("Expected error, but no error returned")
|
||
|
}
|
||
|
} else {
|
||
|
if err != nil {
|
||
|
t.Fatalf("Test %q failed: %v", k, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestResourceProvisioner_windowsDefaultCertname(t *testing.T) {
|
||
|
cases := map[string]struct {
|
||
|
Config map[string]interface{}
|
||
|
Commands map[string]bool
|
||
|
CommandFunc func(*remote.Cmd) error
|
||
|
ExpectedError bool
|
||
|
}{
|
||
|
"GetHostByName failure": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case getHostByNameCmd:
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: getHostByNameCmd,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
"GetHostByName returns FQDN": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case getHostByNameCmd:
|
||
|
r.Stdout.Write([]byte("example.test.com\n"))
|
||
|
time.Sleep(200 * time.Millisecond)
|
||
|
r.SetExitStatus(0, nil)
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
},
|
||
|
"GetHostByName returns hostname, DNSDomain query succeeds": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case getHostByNameCmd:
|
||
|
r.Stdout.Write([]byte("example\n"))
|
||
|
time.Sleep(200 * time.Millisecond)
|
||
|
r.SetExitStatus(0, nil)
|
||
|
case domainQueryCmd:
|
||
|
r.Stdout.Write([]byte("test.com\n"))
|
||
|
time.Sleep(200 * time.Millisecond)
|
||
|
r.SetExitStatus(0, nil)
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
},
|
||
|
"GetHostByName returns hostname, DNSDomain query fails": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case getHostByNameCmd:
|
||
|
r.Stdout.Write([]byte("example\n"))
|
||
|
time.Sleep(200 * time.Millisecond)
|
||
|
r.SetExitStatus(0, nil)
|
||
|
case domainQueryCmd:
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: domainQueryCmd,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for k, tc := range cases {
|
||
|
p, err := decodeConfig(
|
||
|
schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Error: %v", err)
|
||
|
}
|
||
|
|
||
|
c := new(communicator.MockCommunicator)
|
||
|
c.Commands = tc.Commands
|
||
|
if tc.CommandFunc != nil {
|
||
|
c.CommandFunc = tc.CommandFunc
|
||
|
}
|
||
|
p.comm = c
|
||
|
p.output = new(terraform.MockUIOutput)
|
||
|
|
||
|
_, err = p.windowsDefaultCertname()
|
||
|
if tc.ExpectedError {
|
||
|
if err == nil {
|
||
|
t.Fatalf("Expected error, but no error returned")
|
||
|
}
|
||
|
} else {
|
||
|
if err != nil {
|
||
|
t.Fatalf("Test %q failed: %v", k, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestResourceProvisioner_windowsInstallPuppetAgent(t *testing.T) {
|
||
|
cases := map[string]struct {
|
||
|
Config map[string]interface{}
|
||
|
Commands map[string]bool
|
||
|
CommandFunc func(*remote.Cmd) error
|
||
|
ExpectedError bool
|
||
|
}{
|
||
|
"Everything runs succcessfully": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
Commands: map[string]bool{
|
||
|
downloadInstallerCmd: true,
|
||
|
runInstallerCmd: true,
|
||
|
},
|
||
|
},
|
||
|
"Installer download fails": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": true,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case downloadInstallerCmd:
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: downloadInstallerCmd,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
"Install script fails": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
switch r.Command {
|
||
|
case downloadInstallerCmd:
|
||
|
r.SetExitStatus(0, nil)
|
||
|
case runInstallerCmd:
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: runInstallerCmd,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
default:
|
||
|
return fmt.Errorf("Command not found!")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for k, tc := range cases {
|
||
|
p, err := decodeConfig(
|
||
|
schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Error: %v", err)
|
||
|
}
|
||
|
|
||
|
c := new(communicator.MockCommunicator)
|
||
|
c.Commands = tc.Commands
|
||
|
if tc.CommandFunc != nil {
|
||
|
c.CommandFunc = tc.CommandFunc
|
||
|
}
|
||
|
p.comm = c
|
||
|
p.output = new(terraform.MockUIOutput)
|
||
|
|
||
|
err = p.windowsInstallPuppetAgent()
|
||
|
if tc.ExpectedError {
|
||
|
if err == nil {
|
||
|
t.Fatalf("Expected error, but no error returned")
|
||
|
}
|
||
|
} else {
|
||
|
if err != nil {
|
||
|
t.Fatalf("Test %q failed: %v", k, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestResourceProvisioner_windowsRunPuppetAgent(t *testing.T) {
|
||
|
cases := map[string]struct {
|
||
|
Config map[string]interface{}
|
||
|
Commands map[string]bool
|
||
|
CommandFunc func(*remote.Cmd) error
|
||
|
ExpectedError bool
|
||
|
}{
|
||
|
"When puppet returns 0": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
Commands: map[string]bool{
|
||
|
runPuppetCmd: true,
|
||
|
},
|
||
|
},
|
||
|
"When puppet returns 2 (changes applied without error)": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
r.SetExitStatus(2, &remote.ExitError{
|
||
|
Command: runPuppetCmd,
|
||
|
ExitStatus: 2,
|
||
|
Err: nil,
|
||
|
})
|
||
|
return nil
|
||
|
},
|
||
|
},
|
||
|
"When puppet returns something not 0 or 2": {
|
||
|
Config: map[string]interface{}{
|
||
|
"server": "puppet.test.com",
|
||
|
"use_sudo": false,
|
||
|
},
|
||
|
CommandFunc: func(r *remote.Cmd) error {
|
||
|
r.SetExitStatus(1, &remote.ExitError{
|
||
|
Command: runPuppetCmd,
|
||
|
ExitStatus: 1,
|
||
|
Err: nil,
|
||
|
})
|
||
|
return nil
|
||
|
},
|
||
|
ExpectedError: true,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for k, tc := range cases {
|
||
|
p, err := decodeConfig(
|
||
|
schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Error: %v", err)
|
||
|
}
|
||
|
|
||
|
c := new(communicator.MockCommunicator)
|
||
|
c.Commands = tc.Commands
|
||
|
if tc.CommandFunc != nil {
|
||
|
c.CommandFunc = tc.CommandFunc
|
||
|
}
|
||
|
p.comm = c
|
||
|
p.output = new(terraform.MockUIOutput)
|
||
|
|
||
|
err = p.windowsRunPuppetAgent()
|
||
|
if tc.ExpectedError {
|
||
|
if err == nil {
|
||
|
t.Fatalf("Expected error, but no error returned")
|
||
|
}
|
||
|
} else {
|
||
|
if err != nil {
|
||
|
t.Fatalf("Test %q failed: %v", k, err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|