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

     1  package vmcx
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"io/ioutil"
    10  	"os"
    11  
    12  	hypervcommon "github.com/hashicorp/packer/builder/hyperv/common"
    13  	"github.com/hashicorp/packer/helper/multistep"
    14  	"github.com/hashicorp/packer/packer"
    15  )
    16  
    17  func testConfig() map[string]interface{} {
    18  	return map[string]interface{}{
    19  		"iso_checksum":            "foo",
    20  		"iso_checksum_type":       "md5",
    21  		"iso_url":                 "http://www.packer.io",
    22  		"shutdown_command":        "yes",
    23  		"ssh_username":            "foo",
    24  		"switch_name":             "switch", // to avoid using builder.detectSwitchName which can lock down in travis-ci
    25  		"ram_size":                64,
    26  		"guest_additions_mode":    "none",
    27  		"clone_from_vmcx_path":    "generated",
    28  		packer.BuildNameConfigKey: "foo",
    29  	}
    30  }
    31  
    32  func TestBuilder_ImplementsBuilder(t *testing.T) {
    33  	var raw interface{}
    34  	raw = &Builder{}
    35  	if _, ok := raw.(packer.Builder); !ok {
    36  		t.Error("Builder must implement builder.")
    37  	}
    38  }
    39  
    40  func TestBuilderPrepare_Defaults(t *testing.T) {
    41  	var b Builder
    42  	config := testConfig()
    43  
    44  	//Create vmcx folder
    45  	td, err := ioutil.TempDir("", "packer")
    46  	if err != nil {
    47  		t.Fatalf("err: %s", err)
    48  	}
    49  	defer os.RemoveAll(td)
    50  	config["clone_from_vmcx_path"] = td
    51  
    52  	warns, err := b.Prepare(config)
    53  	if len(warns) > 0 {
    54  		t.Fatalf("bad: %#v", warns)
    55  	}
    56  	if err != nil {
    57  		t.Fatalf("should not have error: %s", err)
    58  	}
    59  
    60  	if b.config.VMName != "packer-foo" {
    61  		t.Errorf("bad vm name: %s", b.config.VMName)
    62  	}
    63  }
    64  
    65  func TestBuilderPrepare_InvalidKey(t *testing.T) {
    66  	var b Builder
    67  	config := testConfig()
    68  
    69  	//Create vmcx folder
    70  	td, err := ioutil.TempDir("", "packer")
    71  	if err != nil {
    72  		t.Fatalf("err: %s", err)
    73  	}
    74  	defer os.RemoveAll(td)
    75  	config["clone_from_vmcx_path"] = td
    76  
    77  	// Add a random key
    78  	config["i_should_not_be_valid"] = true
    79  	warns, err := b.Prepare(config)
    80  	if len(warns) > 0 {
    81  		t.Fatalf("bad: %#v", warns)
    82  	}
    83  	if err == nil {
    84  		t.Fatal("should have error")
    85  	}
    86  }
    87  
    88  func TestBuilderPrepare_CloneFromExistingMachineOrImportFromExportedMachineSettingsRequired(t *testing.T) {
    89  	var b Builder
    90  	config := testConfig()
    91  	delete(config, "clone_from_vmcx_path")
    92  
    93  	warns, err := b.Prepare(config)
    94  	if len(warns) > 0 {
    95  		t.Fatalf("bad: %#v", warns)
    96  	}
    97  	if err == nil {
    98  		t.Fatal("should have error")
    99  	}
   100  }
   101  
   102  func TestBuilderPrepare_ExportedMachinePathDoesNotExist(t *testing.T) {
   103  	var b Builder
   104  	config := testConfig()
   105  
   106  	//Create vmcx folder
   107  	td, err := ioutil.TempDir("", "packer")
   108  	if err != nil {
   109  		t.Fatalf("err: %s", err)
   110  	}
   111  
   112  	//Delete the folder immediately
   113  	os.RemoveAll(td)
   114  
   115  	config["clone_from_vmcx_path"] = td
   116  
   117  	warns, err := b.Prepare(config)
   118  	if len(warns) > 0 {
   119  		t.Fatalf("bad: %#v", warns)
   120  	}
   121  	if err == nil {
   122  		t.Fatal("should have error")
   123  	}
   124  }
   125  
   126  func TestBuilderPrepare_ExportedMachinePathExists(t *testing.T) {
   127  	var b Builder
   128  	config := testConfig()
   129  
   130  	//Create vmcx folder
   131  	td, err := ioutil.TempDir("", "packer")
   132  	if err != nil {
   133  		t.Fatalf("err: %s", err)
   134  	}
   135  
   136  	//Only delete afterwards
   137  	defer os.RemoveAll(td)
   138  
   139  	config["clone_from_vmcx_path"] = td
   140  
   141  	warns, err := b.Prepare(config)
   142  	if len(warns) > 0 {
   143  		t.Fatalf("bad: %#v", warns)
   144  	}
   145  	if err != nil {
   146  		t.Fatalf("should not have error: %s", err)
   147  	}
   148  }
   149  
   150  func disabled_TestBuilderPrepare_CloneFromVmSettingUsedSoNoCloneFromVmcxPathRequired(t *testing.T) {
   151  	var b Builder
   152  	config := testConfig()
   153  	delete(config, "clone_from_vmcx_path")
   154  
   155  	config["clone_from_vm_name"] = "test_machine_name_that_does_not_exist"
   156  
   157  	warns, err := b.Prepare(config)
   158  	if len(warns) > 0 {
   159  		t.Fatalf("bad: %#v", warns)
   160  	}
   161  
   162  	if err == nil {
   163  		t.Fatal("should have error")
   164  	} else {
   165  		errorMessage := err.Error()
   166  		if errorMessage != "1 error(s) occurred:\n\n* Virtual machine 'test_machine_name_that_does_not_exist' "+
   167  			"to clone from does not exist." {
   168  			t.Fatalf("should not have error: %s", err)
   169  		}
   170  	}
   171  }
   172  
   173  func TestBuilderPrepare_ISOChecksum(t *testing.T) {
   174  	var b Builder
   175  	config := testConfig()
   176  
   177  	//Create vmcx folder
   178  	td, err := ioutil.TempDir("", "packer")
   179  	if err != nil {
   180  		t.Fatalf("err: %s", err)
   181  	}
   182  	defer os.RemoveAll(td)
   183  	config["clone_from_vmcx_path"] = td
   184  
   185  	// Test bad
   186  	config["iso_checksum"] = ""
   187  	warns, err := b.Prepare(config)
   188  	if len(warns) > 0 {
   189  		t.Fatalf("bad: %#v", warns)
   190  	}
   191  	if err == nil {
   192  		t.Fatal("should have error")
   193  	}
   194  
   195  	// Test good
   196  	config["iso_checksum"] = "FOo"
   197  	b = Builder{}
   198  	warns, err = b.Prepare(config)
   199  	if len(warns) > 0 {
   200  		t.Fatalf("bad: %#v", warns)
   201  	}
   202  	if err != nil {
   203  		t.Fatalf("should not have error: %s", err)
   204  	}
   205  
   206  	if b.config.ISOChecksum != "foo" {
   207  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksum)
   208  	}
   209  }
   210  
   211  func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
   212  	var b Builder
   213  	config := testConfig()
   214  
   215  	//Create vmcx folder
   216  	td, err := ioutil.TempDir("", "packer")
   217  	if err != nil {
   218  		t.Fatalf("err: %s", err)
   219  	}
   220  	defer os.RemoveAll(td)
   221  	config["clone_from_vmcx_path"] = td
   222  
   223  	// Test bad
   224  	config["iso_checksum_type"] = ""
   225  	warns, err := b.Prepare(config)
   226  	if len(warns) > 0 {
   227  		t.Fatalf("bad: %#v", warns)
   228  	}
   229  	if err == nil {
   230  		t.Fatal("should have error")
   231  	}
   232  
   233  	// Test good
   234  	config["iso_checksum_type"] = "mD5"
   235  	b = Builder{}
   236  	warns, err = b.Prepare(config)
   237  	if len(warns) > 0 {
   238  		t.Fatalf("bad: %#v", warns)
   239  	}
   240  	if err != nil {
   241  		t.Fatalf("should not have error: %s", err)
   242  	}
   243  
   244  	if b.config.ISOChecksumType != "md5" {
   245  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType)
   246  	}
   247  
   248  	// Test unknown
   249  	config["iso_checksum_type"] = "fake"
   250  	b = Builder{}
   251  	warns, err = b.Prepare(config)
   252  	if len(warns) > 0 {
   253  		t.Fatalf("bad: %#v", warns)
   254  	}
   255  	if err == nil {
   256  		t.Fatal("should have error")
   257  	}
   258  
   259  	// Test none
   260  	config["iso_checksum_type"] = "none"
   261  	b = Builder{}
   262  	warns, err = b.Prepare(config)
   263  	if len(warns) == 0 {
   264  		t.Fatalf("bad: %#v", warns)
   265  	}
   266  	if err != nil {
   267  		t.Fatalf("should not have error: %s", err)
   268  	}
   269  
   270  	if b.config.ISOChecksumType != "none" {
   271  		t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType)
   272  	}
   273  }
   274  
   275  func TestBuilderPrepare_ISOUrl(t *testing.T) {
   276  	var b Builder
   277  	config := testConfig()
   278  
   279  	//Create vmcx folder
   280  	td, err := ioutil.TempDir("", "packer")
   281  	if err != nil {
   282  		t.Fatalf("err: %s", err)
   283  	}
   284  	defer os.RemoveAll(td)
   285  	config["clone_from_vmcx_path"] = td
   286  
   287  	delete(config, "iso_url")
   288  	delete(config, "iso_urls")
   289  
   290  	// Test both empty (should be allowed, as we cloning a vm so we probably don't need an ISO file)
   291  	config["iso_url"] = ""
   292  	b = Builder{}
   293  	warns, err := b.Prepare(config)
   294  	if len(warns) > 0 {
   295  		t.Fatalf("bad: %#v", warns)
   296  	}
   297  	if err != nil {
   298  		t.Fatal("should not have an error")
   299  	}
   300  
   301  	// Test iso_url set
   302  	config["iso_url"] = "http://www.packer.io"
   303  	b = Builder{}
   304  	warns, err = b.Prepare(config)
   305  	if len(warns) > 0 {
   306  		t.Fatalf("bad: %#v", warns)
   307  	}
   308  	if err != nil {
   309  		t.Errorf("should not have error: %s", err)
   310  	}
   311  
   312  	expected := []string{"http://www.packer.io"}
   313  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   314  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   315  	}
   316  
   317  	// Test both set
   318  	config["iso_url"] = "http://www.packer.io"
   319  	config["iso_urls"] = []string{"http://www.packer.io"}
   320  	b = Builder{}
   321  	warns, err = b.Prepare(config)
   322  	if len(warns) > 0 {
   323  		t.Fatalf("bad: %#v", warns)
   324  	}
   325  	if err == nil {
   326  		t.Fatal("should have error")
   327  	}
   328  
   329  	// Test just iso_urls set
   330  	delete(config, "iso_url")
   331  	config["iso_urls"] = []string{
   332  		"http://www.packer.io",
   333  		"http://www.hashicorp.com",
   334  	}
   335  
   336  	b = Builder{}
   337  	warns, err = b.Prepare(config)
   338  	if len(warns) > 0 {
   339  		t.Fatalf("bad: %#v", warns)
   340  	}
   341  	if err != nil {
   342  		t.Errorf("should not have error: %s", err)
   343  	}
   344  
   345  	expected = []string{
   346  		"http://www.packer.io",
   347  		"http://www.hashicorp.com",
   348  	}
   349  	if !reflect.DeepEqual(b.config.ISOUrls, expected) {
   350  		t.Fatalf("bad: %#v", b.config.ISOUrls)
   351  	}
   352  }
   353  
   354  func TestBuilderPrepare_FloppyFiles(t *testing.T) {
   355  	var b Builder
   356  	config := testConfig()
   357  
   358  	//Create vmcx folder
   359  	td, err := ioutil.TempDir("", "packer")
   360  	if err != nil {
   361  		t.Fatalf("err: %s", err)
   362  	}
   363  	defer os.RemoveAll(td)
   364  	config["clone_from_vmcx_path"] = td
   365  
   366  	delete(config, "floppy_files")
   367  	warns, err := b.Prepare(config)
   368  	if len(warns) > 0 {
   369  		t.Fatalf("bad: %#v", warns)
   370  	}
   371  	if err != nil {
   372  		t.Fatalf("bad err: %s", err)
   373  	}
   374  
   375  	if len(b.config.FloppyFiles) != 0 {
   376  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   377  	}
   378  
   379  	floppies_path := "../../../common/test-fixtures/floppies"
   380  	config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
   381  	b = Builder{}
   382  	warns, err = b.Prepare(config)
   383  	if len(warns) > 0 {
   384  		t.Fatalf("bad: %#v", warns)
   385  	}
   386  	if err != nil {
   387  		t.Fatalf("should not have error: %s", err)
   388  	}
   389  
   390  	expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
   391  	if !reflect.DeepEqual(b.config.FloppyFiles, expected) {
   392  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   393  	}
   394  }
   395  
   396  func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
   397  	var b Builder
   398  	config := testConfig()
   399  
   400  	//Create vmcx folder
   401  	td, err := ioutil.TempDir("", "packer")
   402  	if err != nil {
   403  		t.Fatalf("err: %s", err)
   404  	}
   405  	defer os.RemoveAll(td)
   406  	config["clone_from_vmcx_path"] = td
   407  
   408  	config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
   409  	b = Builder{}
   410  	_, errs := b.Prepare(config)
   411  	if errs == nil {
   412  		t.Fatalf("Nonexistent floppies should trigger multierror")
   413  	}
   414  
   415  	if len(errs.(*packer.MultiError).Errors) != 2 {
   416  		t.Fatalf("Multierror should work and report 2 errors")
   417  	}
   418  }
   419  
   420  func TestBuilderPrepare_CommConfig(t *testing.T) {
   421  	// Test Winrm
   422  	{
   423  		config := testConfig()
   424  
   425  		//Create vmcx folder
   426  		td, err := ioutil.TempDir("", "packer")
   427  		if err != nil {
   428  			t.Fatalf("err: %s", err)
   429  		}
   430  		defer os.RemoveAll(td)
   431  		config["clone_from_vmcx_path"] = td
   432  
   433  		config["communicator"] = "winrm"
   434  		config["winrm_username"] = "username"
   435  		config["winrm_password"] = "password"
   436  		config["winrm_host"] = "1.2.3.4"
   437  
   438  		var 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.Fatalf("should not have error: %s", err)
   445  		}
   446  
   447  		if b.config.Comm.WinRMUser != "username" {
   448  			t.Errorf("bad winrm_username: %s", b.config.Comm.WinRMUser)
   449  		}
   450  		if b.config.Comm.WinRMPassword != "password" {
   451  			t.Errorf("bad winrm_password: %s", b.config.Comm.WinRMPassword)
   452  		}
   453  		if host := b.config.Comm.Host(); host != "1.2.3.4" {
   454  			t.Errorf("bad host: %s", host)
   455  		}
   456  	}
   457  
   458  	// Test SSH
   459  	{
   460  		config := testConfig()
   461  
   462  		//Create vmcx folder
   463  		td, err := ioutil.TempDir("", "packer")
   464  		if err != nil {
   465  			t.Fatalf("err: %s", err)
   466  		}
   467  		defer os.RemoveAll(td)
   468  		config["clone_from_vmcx_path"] = td
   469  
   470  		config["communicator"] = "ssh"
   471  		config["ssh_username"] = "username"
   472  		config["ssh_password"] = "password"
   473  		config["ssh_host"] = "1.2.3.4"
   474  
   475  		var b Builder
   476  		warns, err := b.Prepare(config)
   477  		if len(warns) > 0 {
   478  			t.Fatalf("bad: %#v", warns)
   479  		}
   480  		if err != nil {
   481  			t.Fatalf("should not have error: %s", err)
   482  		}
   483  
   484  		if b.config.Comm.SSHUsername != "username" {
   485  			t.Errorf("bad ssh_username: %s", b.config.Comm.SSHUsername)
   486  		}
   487  		if b.config.Comm.SSHPassword != "password" {
   488  			t.Errorf("bad ssh_password: %s", b.config.Comm.SSHPassword)
   489  		}
   490  		if host := b.config.Comm.Host(); host != "1.2.3.4" {
   491  			t.Errorf("bad host: %s", host)
   492  		}
   493  	}
   494  }
   495  
   496  func TestUserVariablesInBootCommand(t *testing.T) {
   497  	var b Builder
   498  	config := testConfig()
   499  
   500  	//Create vmcx folder
   501  	td, err := ioutil.TempDir("", "packer")
   502  	if err != nil {
   503  		t.Fatalf("err: %s", err)
   504  	}
   505  	defer os.RemoveAll(td)
   506  	config["clone_from_vmcx_path"] = td
   507  
   508  	config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"}
   509  	config["boot_command"] = []string{"blah {{user `test-variable`}} blah"}
   510  
   511  	warns, err := b.Prepare(config)
   512  	if len(warns) > 0 {
   513  		t.Fatalf("bad: %#v", warns)
   514  	}
   515  	if err != nil {
   516  		t.Fatalf("should not have error: %s", err)
   517  	}
   518  
   519  	ui := packer.TestUi(t)
   520  	cache := &packer.FileCache{CacheDir: os.TempDir()}
   521  	hook := &packer.MockHook{}
   522  	driver := &hypervcommon.DriverMock{}
   523  
   524  	// Set up the state.
   525  	state := new(multistep.BasicStateBag)
   526  	state.Put("cache", cache)
   527  	state.Put("config", &b.config)
   528  	state.Put("driver", driver)
   529  	state.Put("hook", hook)
   530  	state.Put("http_port", uint(0))
   531  	state.Put("ui", ui)
   532  	state.Put("vmName", "packer-foo")
   533  
   534  	step := &hypervcommon.StepTypeBootCommand{
   535  		BootCommand: b.config.FlatBootCommand(),
   536  		SwitchName:  b.config.SwitchName,
   537  		Ctx:         b.config.ctx,
   538  	}
   539  
   540  	ret := step.Run(context.Background(), state)
   541  	if ret != multistep.ActionContinue {
   542  		t.Fatalf("should not have error: %#v", ret)
   543  	}
   544  }