2015-06-21 10:53:08 -04:00
package iso
import (
2018-01-22 19:03:49 -05:00
"context"
2017-06-20 07:21:07 -04:00
"fmt"
2015-06-21 10:53:08 -04:00
"reflect"
2017-10-19 18:29:17 -04:00
"strconv"
2015-06-21 10:53:08 -04:00
"testing"
2016-06-30 15:21:57 -04:00
2018-01-22 20:21:10 -05:00
"os"
2017-11-05 08:58:08 -05:00
hypervcommon "github.com/hashicorp/packer/builder/hyperv/common"
2018-01-19 19:18:44 -05:00
"github.com/hashicorp/packer/helper/multistep"
2017-05-29 20:16:03 -04:00
"github.com/hashicorp/packer/packer"
2015-06-21 10:53:08 -04:00
)
func testConfig ( ) map [ string ] interface { } {
return map [ string ] interface { } {
2015-10-30 16:13:48 -04:00
"iso_checksum" : "foo" ,
"iso_checksum_type" : "md5" ,
"iso_url" : "http://www.packer.io" ,
"shutdown_command" : "yes" ,
"ssh_username" : "foo" ,
2016-11-06 10:51:48 -05:00
"ram_size" : 64 ,
2015-10-30 16:13:48 -04:00
"disk_size" : 256 ,
2018-02-23 14:19:26 -05:00
"disk_block_size" : 1 ,
2015-10-30 16:13:48 -04:00
"guest_additions_mode" : "none" ,
2017-10-19 18:29:17 -04:00
"disk_additional_size" : "50000,40000,30000" ,
2015-06-21 10:53:08 -04:00
packer . BuildNameConfigKey : "foo" ,
}
}
func TestBuilder_ImplementsBuilder ( t * testing . T ) {
var raw interface { }
raw = & Builder { }
if _ , ok := raw . ( packer . Builder ) ; ! ok {
t . Error ( "Builder must implement builder." )
}
}
func TestBuilderPrepare_Defaults ( t * testing . T ) {
var b Builder
config := testConfig ( )
2016-06-30 15:21:57 -04:00
2015-06-21 10:53:08 -04:00
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . VMName != "packer-foo" {
t . Errorf ( "bad vm name: %s" , b . config . VMName )
}
}
func TestBuilderPrepare_DiskSize ( t * testing . T ) {
var b Builder
config := testConfig ( )
delete ( config , "disk_size" )
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "bad err: %s" , err )
}
2015-10-30 16:13:48 -04:00
if b . config . DiskSize != 40 * 1024 {
2015-06-21 10:53:08 -04:00
t . Fatalf ( "bad size: %d" , b . config . DiskSize )
}
2015-10-18 12:11:38 -04:00
config [ "disk_size" ] = 256
2015-06-21 10:53:08 -04:00
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
2015-10-18 12:11:38 -04:00
if b . config . DiskSize != 256 {
2015-06-21 10:53:08 -04:00
t . Fatalf ( "bad size: %d" , b . config . DiskSize )
}
}
2018-02-23 14:19:26 -05:00
func TestBuilderPrepare_DiskBlockSize ( t * testing . T ) {
var b Builder
config := testConfig ( )
expected_default_block_size := uint ( 32 )
expected_min_block_size := uint ( 0 )
expected_max_block_size := uint ( 256 )
// Test default with empty disk_block_size
delete ( config , "disk_block_size" )
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "bad err: %s" , err )
}
if b . config . DiskBlockSize != expected_default_block_size {
t . Fatalf ( "bad default block size with empty config: %d. Expected %d" , b . config . DiskBlockSize , expected_default_block_size )
}
test_sizes := [ ] uint { 0 , 1 , 32 , 256 , 512 , 1 * 1024 , 32 * 1024 }
for _ , test_size := range test_sizes {
config [ "disk_block_size" ] = test_size
b = Builder { }
warns , err = b . Prepare ( config )
if test_size > expected_max_block_size || test_size < expected_min_block_size {
if len ( warns ) > 0 {
t . Fatalf ( "bad, should have no warns: %#v" , warns )
}
if err == nil {
t . Fatalf ( "bad, should have error but didn't. disk_block_size=%d outside expected valid range [%d,%d]" , test_size , expected_min_block_size , expected_max_block_size )
}
} else {
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "bad, should not have error: %s" , err )
}
if test_size == 0 {
if b . config . DiskBlockSize != expected_default_block_size {
t . Fatalf ( "bad default block size with 0 value config: %d. Expected: %d" , b . config . DiskBlockSize , expected_default_block_size )
}
} else {
if b . config . DiskBlockSize != test_size {
t . Fatalf ( "bad block size with 0 value config: %d. Expected: %d" , b . config . DiskBlockSize , expected_default_block_size )
}
}
}
}
}
2018-04-20 15:13:12 -04:00
func TestBuilderPrepare_FixedVHDFormat ( t * testing . T ) {
var b Builder
config := testConfig ( )
config [ "use_fixed_vhd_format" ] = true
config [ "generation" ] = 1
config [ "skip_compaction" ] = true
config [ "differencing_disk" ] = false
//use_fixed_vhd_format should work with generation = 1, skip_compaction = true, and differencing_disk = false
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "bad err: %s" , err )
}
//use_fixed_vhd_format should not work with differencing_disk = true
config [ "differencing_disk" ] = true
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
config [ "differencing_disk" ] = false
//use_fixed_vhd_format should not work with skip_compaction = false
config [ "skip_compaction" ] = false
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
config [ "skip_compaction" ] = true
//use_fixed_vhd_format should not work with generation = 2
config [ "generation" ] = 2
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
}
2017-06-20 07:21:07 -04:00
func TestBuilderPrepare_FloppyFiles ( t * testing . T ) {
var b Builder
config := testConfig ( )
delete ( config , "floppy_files" )
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "bad err: %s" , err )
}
if len ( b . config . FloppyFiles ) != 0 {
t . Fatalf ( "bad: %#v" , b . config . FloppyFiles )
}
floppiesPath := "../../../common/test-fixtures/floppies"
config [ "floppy_files" ] = [ ] string { fmt . Sprintf ( "%s/bar.bat" , floppiesPath ) , fmt . Sprintf ( "%s/foo.ps1" , floppiesPath ) }
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
expected := [ ] string { fmt . Sprintf ( "%s/bar.bat" , floppiesPath ) , fmt . Sprintf ( "%s/foo.ps1" , floppiesPath ) }
if ! reflect . DeepEqual ( b . config . FloppyFiles , expected ) {
t . Fatalf ( "bad: %#v" , b . config . FloppyFiles )
}
}
func TestBuilderPrepare_InvalidFloppies ( t * testing . T ) {
var b Builder
config := testConfig ( )
config [ "floppy_files" ] = [ ] string { "nonexistent.bat" , "nonexistent.ps1" }
b = Builder { }
_ , errs := b . Prepare ( config )
if errs == nil {
t . Fatalf ( "Nonexistent floppies should trigger multierror" )
}
if len ( errs . ( * packer . MultiError ) . Errors ) != 2 {
t . Fatalf ( "Multierror should work and report 2 errors" )
}
}
2015-06-21 10:53:08 -04:00
func TestBuilderPrepare_InvalidKey ( t * testing . T ) {
var b Builder
config := testConfig ( )
// Add a random key
config [ "i_should_not_be_valid" ] = true
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
}
func TestBuilderPrepare_ISOChecksum ( t * testing . T ) {
var b Builder
config := testConfig ( )
// Test bad
config [ "iso_checksum" ] = ""
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
// Test good
config [ "iso_checksum" ] = "FOo"
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . ISOChecksum != "foo" {
t . Fatalf ( "should've lowercased: %s" , b . config . ISOChecksum )
}
}
func TestBuilderPrepare_ISOChecksumType ( t * testing . T ) {
var b Builder
config := testConfig ( )
// Test bad
config [ "iso_checksum_type" ] = ""
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
// Test good
config [ "iso_checksum_type" ] = "mD5"
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . ISOChecksumType != "md5" {
t . Fatalf ( "should've lowercased: %s" , b . config . ISOChecksumType )
}
// Test unknown
config [ "iso_checksum_type" ] = "fake"
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
// Test none
config [ "iso_checksum_type" ] = "none"
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) == 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . ISOChecksumType != "none" {
t . Fatalf ( "should've lowercased: %s" , b . config . ISOChecksumType )
}
}
func TestBuilderPrepare_ISOUrl ( t * testing . T ) {
var b Builder
config := testConfig ( )
delete ( config , "iso_url" )
delete ( config , "iso_urls" )
2017-05-21 12:29:26 -04:00
// Test both empty
2015-06-21 10:53:08 -04:00
config [ "iso_url" ] = ""
b = Builder { }
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
// Test iso_url set
config [ "iso_url" ] = "http://www.packer.io"
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Errorf ( "should not have error: %s" , err )
}
expected := [ ] string { "http://www.packer.io" }
if ! reflect . DeepEqual ( b . config . ISOUrls , expected ) {
t . Fatalf ( "bad: %#v" , b . config . ISOUrls )
}
// Test both set
config [ "iso_url" ] = "http://www.packer.io"
config [ "iso_urls" ] = [ ] string { "http://www.packer.io" }
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Fatal ( "should have error" )
}
// Test just iso_urls set
delete ( config , "iso_url" )
config [ "iso_urls" ] = [ ] string {
"http://www.packer.io" ,
"http://www.hashicorp.com" ,
}
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Errorf ( "should not have error: %s" , err )
}
expected = [ ] string {
"http://www.packer.io" ,
"http://www.hashicorp.com" ,
}
if ! reflect . DeepEqual ( b . config . ISOUrls , expected ) {
t . Fatalf ( "bad: %#v" , b . config . ISOUrls )
}
}
2017-05-28 20:51:50 -04:00
2017-05-28 21:36:01 -04:00
func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive ( t * testing . T ) {
var b Builder
config := testConfig ( )
delete ( config , "iso_url" )
delete ( config , "iso_urls" )
delete ( config , "disk_size" )
config [ "disk_size" ] = 1
// Test just iso_urls set but with vhdx
delete ( config , "iso_url" )
config [ "iso_urls" ] = [ ] string {
"http://www.packer.io/hdd.vhdx" ,
"http://www.hashicorp.com/dvd.iso" ,
}
b = Builder { }
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Errorf ( "should not have error: %s" , err )
}
expected := [ ] string {
"http://www.packer.io/hdd.vhdx" ,
"http://www.hashicorp.com/dvd.iso" ,
}
if ! reflect . DeepEqual ( b . config . ISOUrls , expected ) {
t . Fatalf ( "bad: %#v" , b . config . ISOUrls )
}
// Test just iso_urls set but with vhd
delete ( config , "iso_url" )
config [ "iso_urls" ] = [ ] string {
"http://www.packer.io/hdd.vhd" ,
"http://www.hashicorp.com/dvd.iso" ,
}
b = Builder { }
warns , err = b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Errorf ( "should not have error: %s" , err )
}
expected = [ ] string {
"http://www.packer.io/hdd.vhd" ,
"http://www.hashicorp.com/dvd.iso" ,
}
if ! reflect . DeepEqual ( b . config . ISOUrls , expected ) {
t . Fatalf ( "bad: %#v" , b . config . ISOUrls )
}
}
func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive ( t * testing . T ) {
var b Builder
config := testConfig ( )
delete ( config , "iso_url" )
delete ( config , "iso_urls" )
delete ( config , "disk_size" )
config [ "disk_size" ] = 1
// Test just iso_urls set but with vhdx
delete ( config , "iso_url" )
config [ "iso_urls" ] = [ ] string {
"http://www.packer.io/os.iso" ,
"http://www.hashicorp.com/dvd.iso" ,
}
b = Builder { }
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Errorf ( "should have error" )
}
expected := [ ] string {
"http://www.packer.io/os.iso" ,
"http://www.hashicorp.com/dvd.iso" ,
}
if ! reflect . DeepEqual ( b . config . ISOUrls , expected ) {
t . Fatalf ( "bad: %#v" , b . config . ISOUrls )
}
}
2017-10-19 18:29:17 -04:00
func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks ( t * testing . T ) {
var b Builder
config := testConfig ( )
disks := make ( [ ] string , 65 )
for i := range disks {
disks [ i ] = strconv . Itoa ( i )
}
config [ "disk_additional_size" ] = disks
b = Builder { }
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err == nil {
t . Errorf ( "should have error" )
}
}
2017-05-28 20:51:50 -04:00
func TestBuilderPrepare_CommConfig ( t * testing . T ) {
// Test Winrm
{
config := testConfig ( )
config [ "communicator" ] = "winrm"
config [ "winrm_username" ] = "username"
config [ "winrm_password" ] = "password"
config [ "winrm_host" ] = "1.2.3.4"
var b Builder
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . Comm . WinRMUser != "username" {
t . Errorf ( "bad winrm_username: %s" , b . config . Comm . WinRMUser )
}
if b . config . Comm . WinRMPassword != "password" {
t . Errorf ( "bad winrm_password: %s" , b . config . Comm . WinRMPassword )
}
if host := b . config . Comm . Host ( ) ; host != "1.2.3.4" {
t . Errorf ( "bad host: %s" , host )
}
}
// Test SSH
{
config := testConfig ( )
config [ "communicator" ] = "ssh"
config [ "ssh_username" ] = "username"
config [ "ssh_password" ] = "password"
config [ "ssh_host" ] = "1.2.3.4"
var b Builder
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
if b . config . Comm . SSHUsername != "username" {
t . Errorf ( "bad ssh_username: %s" , b . config . Comm . SSHUsername )
}
if b . config . Comm . SSHPassword != "password" {
t . Errorf ( "bad ssh_password: %s" , b . config . Comm . SSHPassword )
}
if host := b . config . Comm . Host ( ) ; host != "1.2.3.4" {
t . Errorf ( "bad host: %s" , host )
}
}
2017-10-19 18:29:17 -04:00
2017-05-28 20:51:50 -04:00
}
2017-11-05 08:58:08 -05:00
func TestUserVariablesInBootCommand ( t * testing . T ) {
var b Builder
config := testConfig ( )
config [ packer . UserVariablesConfigKey ] = map [ string ] string { "test-variable" : "test" }
config [ "boot_command" ] = [ ] string { "blah {{user `test-variable`}} blah" }
warns , err := b . Prepare ( config )
if len ( warns ) > 0 {
t . Fatalf ( "bad: %#v" , warns )
}
if err != nil {
t . Fatalf ( "should not have error: %s" , err )
}
ui := packer . TestUi ( t )
cache := & packer . FileCache { CacheDir : os . TempDir ( ) }
hook := & packer . MockHook { }
driver := & hypervcommon . DriverMock { }
// Set up the state.
state := new ( multistep . BasicStateBag )
state . Put ( "cache" , cache )
state . Put ( "config" , & b . config )
state . Put ( "driver" , driver )
state . Put ( "hook" , hook )
state . Put ( "http_port" , uint ( 0 ) )
state . Put ( "ui" , ui )
state . Put ( "vmName" , "packer-foo" )
step := & hypervcommon . StepTypeBootCommand {
2018-04-18 19:26:48 -04:00
BootCommand : b . config . FlatBootCommand ( ) ,
2017-11-05 08:58:08 -05:00
SwitchName : b . config . SwitchName ,
Ctx : b . config . ctx ,
}
2018-01-22 19:03:49 -05:00
ret := step . Run ( context . Background ( ) , state )
2017-11-05 08:58:08 -05:00
if ret != multistep . ActionContinue {
2017-11-15 20:01:53 -05:00
t . Fatalf ( "should not have error: %#v" , ret )
2017-11-05 08:58:08 -05:00
}
}