github.phpd.cn/hashicorp/packer@v1.3.2/builder/hyperv/iso/builder_test.go (about)

     1  // +build !windows
     2  
     3  package iso
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"reflect"
     9  	"strconv"
    10  	"testing"
    11  
    12  	"os"
    13  
    14  	hypervcommon "github.com/hashicorp/packer/builder/hyperv/common"
    15  	"github.com/hashicorp/packer/helper/multistep"
    16  	"github.com/hashicorp/packer/packer"
    17  )
    18  
    19  func testConfig() map[string]interface{} {
    20  	return map[string]interface{}{
    21  		"iso_checksum":            "foo",
    22  		"iso_checksum_type":       "md5",
    23  		"iso_url":                 "http://www.packer.io",
    24  		"shutdown_command":        "yes",
    25  		"ssh_username":            "foo",
    26  		"ram_size":                64,
    27  		"disk_size":               256,
    28  		"disk_block_size":         1,
    29  		"guest_additions_mode":    "none",
    30  		"disk_additional_size":    "50000,40000,30000",
    31  		packer.BuildNameConfigKey: "foo",
    32  	}
    33  }
    34  
    35  func TestBuilder_ImplementsBuilder(t *testing.T) {
    36  	var raw interface{}
    37  	raw = &Builder{}
    38  	if _, ok := raw.(packer.Builder); !ok {
    39  		t.Error("Builder must implement builder.")
    40  	}
    41  }
    42  
    43  func TestBuilderPrepare_Defaults(t *testing.T) {
    44  	var b Builder
    45  	config := testConfig()
    46  
    47  	warns, err := b.Prepare(config)
    48  	if len(warns) > 0 {
    49  		t.Fatalf("bad: %#v", warns)
    50  	}
    51  	if err != nil {
    52  		t.Fatalf("should not have error: %s", err)
    53  	}
    54  
    55  	if b.config.VMName != "packer-foo" {
    56  		t.Errorf("bad vm name: %s", b.config.VMName)
    57  	}
    58  }
    59  
    60  func TestBuilderPrepare_DiskSize(t *testing.T) {
    61  	var b Builder
    62  	config := testConfig()
    63  
    64  	delete(config, "disk_size")
    65  	warns, err := b.Prepare(config)
    66  	if len(warns) > 0 {
    67  		t.Fatalf("bad: %#v", warns)
    68  	}
    69  	if err != nil {
    70  		t.Fatalf("bad err: %s", err)
    71  	}
    72  
    73  	if b.config.DiskSize != 40*1024 {
    74  		t.Fatalf("bad size: %d", b.config.DiskSize)
    75  	}
    76  
    77  	config["disk_size"] = 256
    78  	b = Builder{}
    79  	warns, err = b.Prepare(config)
    80  	if len(warns) > 0 {
    81  		t.Fatalf("bad: %#v", warns)
    82  	}
    83  	if err != nil {
    84  		t.Fatalf("should not have error: %s", err)
    85  	}
    86  
    87  	if b.config.DiskSize != 256 {
    88  		t.Fatalf("bad size: %d", b.config.DiskSize)
    89  	}
    90  }
    91  
    92  func TestBuilderPrepare_DiskBlockSize(t *testing.T) {
    93  	var b Builder
    94  	config := testConfig()
    95  	expected_default_block_size := uint(32)
    96  	expected_min_block_size := uint(0)
    97  	expected_max_block_size := uint(256)
    98  
    99  	// Test default with empty disk_block_size
   100  	delete(config, "disk_block_size")
   101  	warns, err := b.Prepare(config)
   102  	if len(warns) > 0 {
   103  		t.Fatalf("bad: %#v", warns)
   104  	}
   105  	if err != nil {
   106  		t.Fatalf("bad err: %s", err)
   107  	}
   108  	if b.config.DiskBlockSize != expected_default_block_size {
   109  		t.Fatalf("bad default block size with empty config: %d. Expected %d", b.config.DiskBlockSize,
   110  			expected_default_block_size)
   111  	}
   112  
   113  	test_sizes := []uint{0, 1, 32, 256, 512, 1 * 1024, 32 * 1024}
   114  	for _, test_size := range test_sizes {
   115  		config["disk_block_size"] = test_size
   116  		b = Builder{}
   117  		warns, err = b.Prepare(config)
   118  		if test_size > expected_max_block_size || test_size < expected_min_block_size {
   119  			if len(warns) > 0 {
   120  				t.Fatalf("bad, should have no warns: %#v", warns)
   121  			}
   122  			if err == nil {
   123  				t.Fatalf("bad, should have error. disk_block_size=%d outside expected valid range [%d,%d]",
   124  					test_size, expected_min_block_size, expected_max_block_size)
   125  			}
   126  		} else {
   127  			if len(warns) > 0 {
   128  				t.Fatalf("bad: %#v", warns)
   129  			}
   130  			if err != nil {
   131  				t.Fatalf("bad, should not have error: %s", err)
   132  			}
   133  			if test_size == 0 {
   134  				if b.config.DiskBlockSize != expected_default_block_size {
   135  					t.Fatalf("bad default block size with 0 value config: %d. Expected: %d",
   136  						b.config.DiskBlockSize, expected_default_block_size)
   137  				}
   138  			} else {
   139  				if b.config.DiskBlockSize != test_size {
   140  					t.Fatalf("bad block size with 0 value config: %d. Expected: %d", b.config.DiskBlockSize,
   141  						expected_default_block_size)
   142  				}
   143  			}
   144  		}
   145  	}
   146  }
   147  
   148  func TestBuilderPrepare_FixedVHDFormat(t *testing.T) {
   149  	var b Builder
   150  	config := testConfig()
   151  	config["use_fixed_vhd_format"] = true
   152  	config["generation"] = 1
   153  	config["skip_compaction"] = true
   154  	config["differencing_disk"] = false
   155  
   156  	// use_fixed_vhd_format should work with generation = 1, skip_compaction
   157  	// = true, and differencing_disk = false
   158  	warns, err := b.Prepare(config)
   159  	if len(warns) > 0 {
   160  		t.Fatalf("bad: %#v", warns)
   161  	}
   162  	if err != nil {
   163  		t.Fatalf("bad err: %s", err)
   164  	}
   165  
   166  	//use_fixed_vhd_format should not work with differencing_disk = true
   167  	config["differencing_disk"] = true
   168  	b = Builder{}
   169  	warns, err = b.Prepare(config)
   170  	if len(warns) > 0 {
   171  		t.Fatalf("bad: %#v", warns)
   172  	}
   173  	if err == nil {
   174  		t.Fatal("should have error")
   175  	}
   176  	config["differencing_disk"] = false
   177  
   178  	//use_fixed_vhd_format should not work with skip_compaction = false
   179  	config["skip_compaction"] = false
   180  	b = Builder{}
   181  	warns, err = b.Prepare(config)
   182  	if len(warns) > 0 {
   183  		t.Fatalf("bad: %#v", warns)
   184  	}
   185  	if err == nil {
   186  		t.Fatal("should have error")
   187  	}
   188  	config["skip_compaction"] = true
   189  
   190  	//use_fixed_vhd_format should not work with generation = 2
   191  	config["generation"] = 2
   192  	b = Builder{}
   193  	warns, err = b.Prepare(config)
   194  	if len(warns) > 0 {
   195  		t.Fatalf("bad: %#v", warns)
   196  	}
   197  	if err == nil {
   198  		t.Fatal("should have error")
   199  	}
   200  }
   201  
   202  func TestBuilderPrepare_FloppyFiles(t *testing.T) {
   203  	var b Builder
   204  	config := testConfig()
   205  
   206  	delete(config, "floppy_files")
   207  	warns, err := b.Prepare(config)
   208  	if len(warns) > 0 {
   209  		t.Fatalf("bad: %#v", warns)
   210  	}
   211  	if err != nil {
   212  		t.Fatalf("bad err: %s", err)
   213  	}
   214  
   215  	if len(b.config.FloppyFiles) != 0 {
   216  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   217  	}
   218  
   219  	floppiesPath := "../../../common/test-fixtures/floppies"
   220  	config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)}
   221  	b = Builder{}
   222  	warns, err = b.Prepare(config)
   223  	if len(warns) > 0 {
   224  		t.Fatalf("bad: %#v", warns)
   225  	}
   226  	if err != nil {
   227  		t.Fatalf("should not have error: %s", err)
   228  	}
   229  
   230  	expected := []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)}
   231  	if !reflect.DeepEqual(b.config.FloppyFiles, expected) {
   232  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   233  	}
   234  }
   235  
   236  func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
   237  	var b Builder
   238  	config := testConfig()
   239  	config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
   240  	b = Builder{}
   241  	_, errs := b.Prepare(config)
   242  	if errs == nil {
   243  		t.Fatalf("Nonexistent floppies should trigger multierror")
   244  	}
   245  
   246  	if len(errs.(*packer.MultiError).Errors) != 2 {
   247  		t.Fatalf("Multierror should work and report 2 errors")
   248  	}
   249  }
   250  
   251  func TestBuilderPrepare_InvalidKey(t *testing.T) {
   252  	var b Builder
   253  	config := testConfig()
   254  
   255  	// Add a random key
   256  	config["i_should_not_be_valid"] = true
   257  	warns, err := b.Prepare(config)
   258  	if len(warns) > 0 {
   259  		t.Fatalf("bad: %#v", warns)
   260  	}
   261  	if err == nil {
   262  		t.Fatal("should have error")
   263  	}
   264  }
   265  
   266  func TestBuilderPrepare_ISOChecksum(t *testing.T) {
   267  	var b Builder
   268  	config := testConfig()
   269  
   270  	// Test bad
   271  	config["iso_checksum"] = ""
   272  	warns, err := b.Prepare(config)
   273  	if len(warns) > 0 {
   274  		t.Fatalf("bad: %#v", warns)
   275  	}
   276  	if err == nil {
   277  		t.Fatal("should have error")
   278  	}
   279  
   280  	// Test good
   281  	config["iso_checksum"] = "FOo"
   282  	b = Builder{}
   283  	warns, err = b.Prepare(config)
   284  	if len(warns) > 0 {
   285  		t.Fatalf("bad: %#v", warns)
   286  	}
   287  	if err != nil {
   288  		t.Fatalf("should not have error: %s", err)
   289  	}
   290  
   291  	if b.config.ISOChecksum != "foo" {
   292  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksum)
   293  	}
   294  }
   295  
   296  func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
   297  	var b Builder
   298  	config := testConfig()
   299  
   300  	// Test bad
   301  	config["iso_checksum_type"] = ""
   302  	warns, err := b.Prepare(config)
   303  	if len(warns) > 0 {
   304  		t.Fatalf("bad: %#v", warns)
   305  	}
   306  	if err == nil {
   307  		t.Fatal("should have error")
   308  	}
   309  
   310  	// Test good
   311  	config["iso_checksum_type"] = "mD5"
   312  	b = Builder{}
   313  	warns, err = b.Prepare(config)
   314  	if len(warns) > 0 {
   315  		t.Fatalf("bad: %#v", warns)
   316  	}
   317  	if err != nil {
   318  		t.Fatalf("should not have error: %s", err)
   319  	}
   320  
   321  	if b.config.ISOChecksumType != "md5" {
   322  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType)
   323  	}
   324  
   325  	// Test unknown
   326  	config["iso_checksum_type"] = "fake"
   327  	b = Builder{}
   328  	warns, err = b.Prepare(config)
   329  	if len(warns) > 0 {
   330  		t.Fatalf("bad: %#v", warns)
   331  	}
   332  	if err == nil {
   333  		t.Fatal("should have error")
   334  	}
   335  
   336  	// Test none
   337  	config["iso_checksum_type"] = "none"
   338  	b = Builder{}
   339  	warns, err = b.Prepare(config)
   340  	if len(warns) == 0 {
   341  		t.Fatalf("bad: %#v", warns)
   342  	}
   343  	if err != nil {
   344  		t.Fatalf("should not have error: %s", err)
   345  	}
   346  
   347  	if b.config.ISOChecksumType != "none" {
   348  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType)
   349  	}
   350  }
   351  
   352  func TestBuilderPrepare_ISOUrl(t *testing.T) {
   353  	var b Builder
   354  	config := testConfig()
   355  	delete(config, "iso_url")
   356  	delete(config, "iso_urls")
   357  
   358  	// Test both empty
   359  	config["iso_url"] = ""
   360  	b = Builder{}
   361  	warns, err := b.Prepare(config)
   362  	if len(warns) > 0 {
   363  		t.Fatalf("bad: %#v", warns)
   364  	}
   365  	if err == nil {
   366  		t.Fatal("should have error")
   367  	}
   368  
   369  	// Test iso_url set
   370  	config["iso_url"] = "http://www.packer.io"
   371  	b = Builder{}
   372  	warns, err = b.Prepare(config)
   373  	if len(warns) > 0 {
   374  		t.Fatalf("bad: %#v", warns)
   375  	}
   376  	if err != nil {
   377  		t.Errorf("should not have error: %s", err)
   378  	}
   379  
   380  	expected := []string{"http://www.packer.io"}
   381  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   382  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   383  	}
   384  
   385  	// Test both set
   386  	config["iso_url"] = "http://www.packer.io"
   387  	config["iso_urls"] = []string{"http://www.packer.io"}
   388  	b = Builder{}
   389  	warns, err = b.Prepare(config)
   390  	if len(warns) > 0 {
   391  		t.Fatalf("bad: %#v", warns)
   392  	}
   393  	if err == nil {
   394  		t.Fatal("should have error")
   395  	}
   396  
   397  	// Test just iso_urls set
   398  	delete(config, "iso_url")
   399  	config["iso_urls"] = []string{
   400  		"http://www.packer.io",
   401  		"http://www.hashicorp.com",
   402  	}
   403  
   404  	b = Builder{}
   405  	warns, err = b.Prepare(config)
   406  	if len(warns) > 0 {
   407  		t.Fatalf("bad: %#v", warns)
   408  	}
   409  	if err != nil {
   410  		t.Errorf("should not have error: %s", err)
   411  	}
   412  
   413  	expected = []string{
   414  		"http://www.packer.io",
   415  		"http://www.hashicorp.com",
   416  	}
   417  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   418  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   419  	}
   420  }
   421  
   422  func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T) {
   423  	var b Builder
   424  	config := testConfig()
   425  	delete(config, "iso_url")
   426  	delete(config, "iso_urls")
   427  	delete(config, "disk_size")
   428  
   429  	config["disk_size"] = 1
   430  
   431  	// Test just iso_urls set but with vhdx
   432  	delete(config, "iso_url")
   433  	config["iso_urls"] = []string{
   434  		"http://www.packer.io/hdd.vhdx",
   435  		"http://www.hashicorp.com/dvd.iso",
   436  	}
   437  
   438  	b = Builder{}
   439  	warns, err := b.Prepare(config)
   440  	if len(warns) > 0 {
   441  		t.Fatalf("bad: %#v", warns)
   442  	}
   443  	if err != nil {
   444  		t.Errorf("should not have error: %s", err)
   445  	}
   446  
   447  	expected := []string{
   448  		"http://www.packer.io/hdd.vhdx",
   449  		"http://www.hashicorp.com/dvd.iso",
   450  	}
   451  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   452  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   453  	}
   454  
   455  	// Test just iso_urls set but with vhd
   456  	delete(config, "iso_url")
   457  	config["iso_urls"] = []string{
   458  		"http://www.packer.io/hdd.vhd",
   459  		"http://www.hashicorp.com/dvd.iso",
   460  	}
   461  
   462  	b = Builder{}
   463  	warns, err = b.Prepare(config)
   464  	if len(warns) > 0 {
   465  		t.Fatalf("bad: %#v", warns)
   466  	}
   467  	if err != nil {
   468  		t.Errorf("should not have error: %s", err)
   469  	}
   470  
   471  	expected = []string{
   472  		"http://www.packer.io/hdd.vhd",
   473  		"http://www.hashicorp.com/dvd.iso",
   474  	}
   475  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   476  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   477  	}
   478  }
   479  
   480  func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive(t *testing.T) {
   481  	var b Builder
   482  	config := testConfig()
   483  	delete(config, "iso_url")
   484  	delete(config, "iso_urls")
   485  	delete(config, "disk_size")
   486  
   487  	config["disk_size"] = 1
   488  
   489  	// Test just iso_urls set but with vhdx
   490  	delete(config, "iso_url")
   491  	config["iso_urls"] = []string{
   492  		"http://www.packer.io/os.iso",
   493  		"http://www.hashicorp.com/dvd.iso",
   494  	}
   495  
   496  	b = Builder{}
   497  	warns, err := b.Prepare(config)
   498  	if len(warns) > 0 {
   499  		t.Fatalf("bad: %#v", warns)
   500  	}
   501  	if err == nil {
   502  		t.Errorf("should have error")
   503  	}
   504  
   505  	expected := []string{
   506  		"http://www.packer.io/os.iso",
   507  		"http://www.hashicorp.com/dvd.iso",
   508  	}
   509  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   510  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   511  	}
   512  }
   513  
   514  func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks(t *testing.T) {
   515  	var b Builder
   516  	config := testConfig()
   517  
   518  	disks := make([]string, 65)
   519  	for i := range disks {
   520  		disks[i] = strconv.Itoa(i)
   521  	}
   522  	config["disk_additional_size"] = disks
   523  
   524  	b = Builder{}
   525  	warns, err := b.Prepare(config)
   526  	if len(warns) > 0 {
   527  		t.Fatalf("bad: %#v", warns)
   528  	}
   529  	if err == nil {
   530  		t.Errorf("should have error")
   531  	}
   532  
   533  }
   534  
   535  func TestBuilderPrepare_CommConfig(t *testing.T) {
   536  	// Test Winrm
   537  	{
   538  		config := testConfig()
   539  		config["communicator"] = "winrm"
   540  		config["winrm_username"] = "username"
   541  		config["winrm_password"] = "password"
   542  		config["winrm_host"] = "1.2.3.4"
   543  
   544  		var b Builder
   545  		warns, err := b.Prepare(config)
   546  		if len(warns) > 0 {
   547  			t.Fatalf("bad: %#v", warns)
   548  		}
   549  		if err != nil {
   550  			t.Fatalf("should not have error: %s", err)
   551  		}
   552  
   553  		if b.config.Comm.WinRMUser != "username" {
   554  			t.Errorf("bad winrm_username: %s", b.config.Comm.WinRMUser)
   555  		}
   556  		if b.config.Comm.WinRMPassword != "password" {
   557  			t.Errorf("bad winrm_password: %s", b.config.Comm.WinRMPassword)
   558  		}
   559  		if host := b.config.Comm.Host(); host != "1.2.3.4" {
   560  			t.Errorf("bad host: %s", host)
   561  		}
   562  	}
   563  
   564  	// Test SSH
   565  	{
   566  		config := testConfig()
   567  		config["communicator"] = "ssh"
   568  		config["ssh_username"] = "username"
   569  		config["ssh_password"] = "password"
   570  		config["ssh_host"] = "1.2.3.4"
   571  
   572  		var b Builder
   573  		warns, err := b.Prepare(config)
   574  		if len(warns) > 0 {
   575  			t.Fatalf("bad: %#v", warns)
   576  		}
   577  		if err != nil {
   578  			t.Fatalf("should not have error: %s", err)
   579  		}
   580  
   581  		if b.config.Comm.SSHUsername != "username" {
   582  			t.Errorf("bad ssh_username: %s", b.config.Comm.SSHUsername)
   583  		}
   584  		if b.config.Comm.SSHPassword != "password" {
   585  			t.Errorf("bad ssh_password: %s", b.config.Comm.SSHPassword)
   586  		}
   587  		if host := b.config.Comm.Host(); host != "1.2.3.4" {
   588  			t.Errorf("bad host: %s", host)
   589  		}
   590  	}
   591  
   592  }
   593  
   594  func TestUserVariablesInBootCommand(t *testing.T) {
   595  	var b Builder
   596  	config := testConfig()
   597  
   598  	config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"}
   599  	config["boot_command"] = []string{"blah {{user `test-variable`}} blah"}
   600  
   601  	warns, err := b.Prepare(config)
   602  	if len(warns) > 0 {
   603  		t.Fatalf("bad: %#v", warns)
   604  	}
   605  	if err != nil {
   606  		t.Fatalf("should not have error: %s", err)
   607  	}
   608  
   609  	ui := packer.TestUi(t)
   610  	cache := &packer.FileCache{CacheDir: os.TempDir()}
   611  	hook := &packer.MockHook{}
   612  	driver := &hypervcommon.DriverMock{}
   613  
   614  	// Set up the state.
   615  	state := new(multistep.BasicStateBag)
   616  	state.Put("cache", cache)
   617  	state.Put("config", &b.config)
   618  	state.Put("driver", driver)
   619  	state.Put("hook", hook)
   620  	state.Put("http_port", uint(0))
   621  	state.Put("ui", ui)
   622  	state.Put("vmName", "packer-foo")
   623  
   624  	step := &hypervcommon.StepTypeBootCommand{
   625  		BootCommand: b.config.FlatBootCommand(),
   626  		SwitchName:  b.config.SwitchName,
   627  		Ctx:         b.config.ctx,
   628  	}
   629  
   630  	ret := step.Run(context.Background(), state)
   631  	if ret != multistep.ActionContinue {
   632  		t.Fatalf("should not have error: %#v", ret)
   633  	}
   634  }