github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/qemu/builder_test.go (about)

     1  package qemu
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/packer/packer"
    11  )
    12  
    13  var testPem = `
    14  -----BEGIN RSA PRIVATE KEY-----
    15  MIIEpQIBAAKCAQEAxd4iamvrwRJvtNDGQSIbNvvIQN8imXTRWlRY62EvKov60vqu
    16  hh+rDzFYAIIzlmrJopvOe0clqmi3mIP9dtkjPFrYflq52a2CF5q+BdwsJXuRHbJW
    17  LmStZUwW1khSz93DhvhmK50nIaczW63u4EO/jJb3xj+wxR1Nkk9bxi3DDsYFt8SN
    18  AzYx9kjlEYQ/+sI4/ATfmdV9h78SVotjScupd9KFzzi76gWq9gwyCBLRynTUWlyD
    19  2UOfJRkOvhN6/jKzvYfVVwjPSfA9IMuooHdScmC4F6KBKJl/zf/zETM0XyzIDNmH
    20  uOPbCiljq2WoRM+rY6ET84EO0kVXbfx8uxUsqQIDAQABAoIBAQCkPj9TF0IagbM3
    21  5BSs/CKbAWS4dH/D4bPlxx4IRCNirc8GUg+MRb04Xz0tLuajdQDqeWpr6iLZ0RKV
    22  BvreLF+TOdV7DNQ4XE4gSdJyCtCaTHeort/aordL3l0WgfI7mVk0L/yfN1PEG4YG
    23  E9q1TYcyrB3/8d5JwIkjabxERLglCcP+geOEJp+QijbvFIaZR/n2irlKW4gSy6ko
    24  9B0fgUnhkHysSg49ChHQBPQ+o5BbpuLrPDFMiTPTPhdfsvGGcyCGeqfBA56oHcSF
    25  K02Fg8OM+Bd1lb48LAN9nWWY4WbwV+9bkN3Ym8hO4c3a/Dxf2N7LtAQqWZzFjvM3
    26  /AaDvAgBAoGBAPLD+Xn1IYQPMB2XXCXfOuJewRY7RzoVWvMffJPDfm16O7wOiW5+
    27  2FmvxUDayk4PZy6wQMzGeGKnhcMMZTyaq2g/QtGfrvy7q1Lw2fB1VFlVblvqhoJa
    28  nMJojjC4zgjBkXMHsRLeTmgUKyGs+fdFbfI6uejBnnf+eMVUMIdJ+6I9AoGBANCn
    29  kWO9640dttyXURxNJ3lBr2H3dJOkmD6XS+u+LWqCSKQe691Y/fZ/ZL0Oc4Mhy7I6
    30  hsy3kDQ5k2V0fkaNODQIFJvUqXw2pMewUk8hHc9403f4fe9cPrL12rQ8WlQw4yoC
    31  v2B61vNczCCUDtGxlAaw8jzSRaSI5s6ax3K7enbdAoGBAJB1WYDfA2CoAQO6y9Sl
    32  b07A/7kQ8SN5DbPaqrDrBdJziBQxukoMJQXJeGFNUFD/DXFU5Fp2R7C86vXT7HIR
    33  v6m66zH+CYzOx/YE6EsUJms6UP9VIVF0Rg/RU7teXQwM01ZV32LQ8mswhTH20o/3
    34  uqMHmxUMEhZpUMhrfq0isyApAoGAe1UxGTXfj9AqkIVYylPIq2HqGww7+jFmVEj1
    35  9Wi6S6Sq72ffnzzFEPkIQL/UA4TsdHMnzsYKFPSbbXLIWUeMGyVTmTDA5c0e5XIR
    36  lPhMOKCAzv8w4VUzMnEkTzkFY5JqFCD/ojW57KvDdNZPVB+VEcdxyAW6aKELXMAc
    37  eHLc1nkCgYEApm/motCTPN32nINZ+Vvywbv64ZD+gtpeMNP3CLrbe1X9O+H52AXa
    38  1jCoOldWR8i2bs2NVPcKZgdo6fFULqE4dBX7Te/uYEIuuZhYLNzRO1IKU/YaqsXG
    39  3bfQ8hKYcSnTfE0gPtLDnqCIxTocaGLSHeG3TH9fTw+dA8FvWpUztI4=
    40  -----END RSA PRIVATE KEY-----
    41  `
    42  
    43  func testConfig() map[string]interface{} {
    44  	return map[string]interface{}{
    45  		"iso_checksum":            "foo",
    46  		"iso_checksum_type":       "md5",
    47  		"iso_url":                 "http://www.google.com/",
    48  		"ssh_username":            "foo",
    49  		packer.BuildNameConfigKey: "foo",
    50  	}
    51  }
    52  
    53  func TestBuilder_ImplementsBuilder(t *testing.T) {
    54  	var raw interface{}
    55  	raw = &Builder{}
    56  	if _, ok := raw.(packer.Builder); !ok {
    57  		t.Error("Builder must implement builder.")
    58  	}
    59  }
    60  
    61  func TestBuilderPrepare_Defaults(t *testing.T) {
    62  	var b Builder
    63  	config := testConfig()
    64  	warns, err := b.Prepare(config)
    65  	if len(warns) > 0 {
    66  		t.Fatalf("bad: %#v", warns)
    67  	}
    68  	if err != nil {
    69  		t.Fatalf("should not have error: %s", err)
    70  	}
    71  
    72  	if b.config.OutputDir != "output-foo" {
    73  		t.Errorf("bad output dir: %s", b.config.OutputDir)
    74  	}
    75  
    76  	if b.config.SSHHostPortMin != 2222 {
    77  		t.Errorf("bad min ssh host port: %d", b.config.SSHHostPortMin)
    78  	}
    79  
    80  	if b.config.SSHHostPortMax != 4444 {
    81  		t.Errorf("bad max ssh host port: %d", b.config.SSHHostPortMax)
    82  	}
    83  
    84  	if b.config.Comm.SSHPort != 22 {
    85  		t.Errorf("bad ssh port: %d", b.config.Comm.SSHPort)
    86  	}
    87  
    88  	if b.config.VMName != "packer-foo" {
    89  		t.Errorf("bad vm name: %s", b.config.VMName)
    90  	}
    91  
    92  	if b.config.Format != "qcow2" {
    93  		t.Errorf("bad format: %s", b.config.Format)
    94  	}
    95  }
    96  
    97  func TestBuilderPrepare_VNCBindAddress(t *testing.T) {
    98  	var b Builder
    99  	config := testConfig()
   100  
   101  	// Test a default boot_wait
   102  	delete(config, "vnc_bind_address")
   103  	warns, err := b.Prepare(config)
   104  	if len(warns) > 0 {
   105  		t.Fatalf("bad: %#v", warns)
   106  	}
   107  	if err != nil {
   108  		t.Fatalf("err: %s", err)
   109  	}
   110  
   111  	if b.config.VNCBindAddress != "127.0.0.1" {
   112  		t.Fatalf("bad value: %s", b.config.VNCBindAddress)
   113  	}
   114  }
   115  
   116  func TestBuilderPrepare_DiskCompaction(t *testing.T) {
   117  	var b Builder
   118  	config := testConfig()
   119  
   120  	// Bad
   121  	config["skip_compaction"] = false
   122  	config["disk_compression"] = true
   123  	config["format"] = "img"
   124  	warns, err := b.Prepare(config)
   125  	if len(warns) > 0 {
   126  		t.Fatalf("bad: %#v", warns)
   127  	}
   128  	if err == nil {
   129  		t.Fatal("should have error")
   130  	}
   131  	if b.config.SkipCompaction != true {
   132  		t.Fatalf("SkipCompaction should be true")
   133  	}
   134  	if b.config.DiskCompression != false {
   135  		t.Fatalf("DiskCompression should be false")
   136  	}
   137  
   138  	// Good
   139  	config["skip_compaction"] = false
   140  	config["disk_compression"] = true
   141  	config["format"] = "qcow2"
   142  	b = Builder{}
   143  	warns, err = b.Prepare(config)
   144  	if len(warns) > 0 {
   145  		t.Fatalf("bad: %#v", warns)
   146  	}
   147  	if err != nil {
   148  		t.Fatalf("should not have error: %s", err)
   149  	}
   150  	if b.config.SkipCompaction != false {
   151  		t.Fatalf("SkipCompaction should be false")
   152  	}
   153  	if b.config.DiskCompression != true {
   154  		t.Fatalf("DiskCompression should be true")
   155  	}
   156  }
   157  
   158  func TestBuilderPrepare_DiskSize(t *testing.T) {
   159  	var b Builder
   160  	config := testConfig()
   161  
   162  	delete(config, "disk_size")
   163  	warns, err := b.Prepare(config)
   164  	if len(warns) > 0 {
   165  		t.Fatalf("bad: %#v", warns)
   166  	}
   167  	if err != nil {
   168  		t.Fatalf("bad err: %s", err)
   169  	}
   170  
   171  	if b.config.DiskSize != 40960 {
   172  		t.Fatalf("bad size: %d", b.config.DiskSize)
   173  	}
   174  
   175  	config["disk_size"] = 60000
   176  	b = Builder{}
   177  	warns, err = b.Prepare(config)
   178  	if len(warns) > 0 {
   179  		t.Fatalf("bad: %#v", warns)
   180  	}
   181  	if err != nil {
   182  		t.Fatalf("should not have error: %s", err)
   183  	}
   184  
   185  	if b.config.DiskSize != 60000 {
   186  		t.Fatalf("bad size: %d", b.config.DiskSize)
   187  	}
   188  }
   189  
   190  func TestBuilderPrepare_Format(t *testing.T) {
   191  	var b Builder
   192  	config := testConfig()
   193  
   194  	// Bad
   195  	config["format"] = "illegal value"
   196  	warns, err := b.Prepare(config)
   197  	if len(warns) > 0 {
   198  		t.Fatalf("bad: %#v", warns)
   199  	}
   200  	if err == nil {
   201  		t.Fatal("should have error")
   202  	}
   203  
   204  	// Good
   205  	config["format"] = "qcow2"
   206  	b = Builder{}
   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("should not have error: %s", err)
   213  	}
   214  
   215  	// Good
   216  	config["format"] = "raw"
   217  	b = Builder{}
   218  	warns, err = b.Prepare(config)
   219  	if len(warns) > 0 {
   220  		t.Fatalf("bad: %#v", warns)
   221  	}
   222  	if err != nil {
   223  		t.Fatalf("should not have error: %s", err)
   224  	}
   225  }
   226  
   227  func TestBuilderPrepare_FloppyFiles(t *testing.T) {
   228  	var b Builder
   229  	config := testConfig()
   230  
   231  	delete(config, "floppy_files")
   232  	warns, err := b.Prepare(config)
   233  	if len(warns) > 0 {
   234  		t.Fatalf("bad: %#v", warns)
   235  	}
   236  	if err != nil {
   237  		t.Fatalf("bad err: %s", err)
   238  	}
   239  
   240  	if len(b.config.FloppyFiles) != 0 {
   241  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   242  	}
   243  
   244  	floppies_path := "../../common/test-fixtures/floppies"
   245  	config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
   246  	b = Builder{}
   247  	warns, err = b.Prepare(config)
   248  	if len(warns) > 0 {
   249  		t.Fatalf("bad: %#v", warns)
   250  	}
   251  	if err != nil {
   252  		t.Fatalf("should not have error: %s", err)
   253  	}
   254  
   255  	expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)}
   256  	if !reflect.DeepEqual(b.config.FloppyFiles, expected) {
   257  		t.Fatalf("bad: %#v", b.config.FloppyFiles)
   258  	}
   259  }
   260  
   261  func TestBuilderPrepare_InvalidFloppies(t *testing.T) {
   262  	var b Builder
   263  	config := testConfig()
   264  	config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"}
   265  	b = Builder{}
   266  	_, errs := b.Prepare(config)
   267  	if errs == nil {
   268  		t.Fatalf("Nonexistent floppies should trigger multierror")
   269  	}
   270  
   271  	if len(errs.(*packer.MultiError).Errors) != 2 {
   272  		t.Fatalf("Multierror should work and report 2 errors")
   273  	}
   274  }
   275  
   276  func TestBuilderPrepare_InvalidKey(t *testing.T) {
   277  	var b Builder
   278  	config := testConfig()
   279  
   280  	// Add a random key
   281  	config["i_should_not_be_valid"] = true
   282  	warns, err := b.Prepare(config)
   283  	if len(warns) > 0 {
   284  		t.Fatalf("bad: %#v", warns)
   285  	}
   286  	if err == nil {
   287  		t.Fatal("should have error")
   288  	}
   289  }
   290  
   291  func TestBuilderPrepare_OutputDir(t *testing.T) {
   292  	var b Builder
   293  	config := testConfig()
   294  
   295  	// Test with existing dir
   296  	dir, err := ioutil.TempDir("", "packer")
   297  	if err != nil {
   298  		t.Fatalf("err: %s", err)
   299  	}
   300  	defer os.RemoveAll(dir)
   301  
   302  	config["output_directory"] = dir
   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.Fatal("should have error")
   310  	}
   311  
   312  	// Test with a good one
   313  	config["output_directory"] = "i-hope-i-dont-exist"
   314  	b = Builder{}
   315  	warns, err = b.Prepare(config)
   316  	if len(warns) > 0 {
   317  		t.Fatalf("bad: %#v", warns)
   318  	}
   319  	if err != nil {
   320  		t.Fatalf("should not have error: %s", err)
   321  	}
   322  }
   323  
   324  func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
   325  	var b Builder
   326  	config := testConfig()
   327  
   328  	// Test with a bad value
   329  	config["shutdown_timeout"] = "this is not good"
   330  	warns, err := b.Prepare(config)
   331  	if len(warns) > 0 {
   332  		t.Fatalf("bad: %#v", warns)
   333  	}
   334  	if err == nil {
   335  		t.Fatal("should have error")
   336  	}
   337  
   338  	// Test with a good one
   339  	config["shutdown_timeout"] = "5s"
   340  	b = Builder{}
   341  	warns, err = b.Prepare(config)
   342  	if len(warns) > 0 {
   343  		t.Fatalf("bad: %#v", warns)
   344  	}
   345  	if err != nil {
   346  		t.Fatalf("should not have error: %s", err)
   347  	}
   348  }
   349  
   350  func TestBuilderPrepare_SSHHostPort(t *testing.T) {
   351  	var b Builder
   352  	config := testConfig()
   353  
   354  	// Bad
   355  	config["ssh_host_port_min"] = 1000
   356  	config["ssh_host_port_max"] = 500
   357  	b = Builder{}
   358  	warns, err := b.Prepare(config)
   359  	if len(warns) > 0 {
   360  		t.Fatalf("bad: %#v", warns)
   361  	}
   362  	if err == nil {
   363  		t.Fatal("should have error")
   364  	}
   365  
   366  	// Bad
   367  	config["ssh_host_port_min"] = -500
   368  	b = Builder{}
   369  	warns, err = b.Prepare(config)
   370  	if len(warns) > 0 {
   371  		t.Fatalf("bad: %#v", warns)
   372  	}
   373  	if err == nil {
   374  		t.Fatal("should have error")
   375  	}
   376  
   377  	// Good
   378  	config["ssh_host_port_min"] = 500
   379  	config["ssh_host_port_max"] = 1000
   380  	b = Builder{}
   381  	warns, err = b.Prepare(config)
   382  	if len(warns) > 0 {
   383  		t.Fatalf("bad: %#v", warns)
   384  	}
   385  	if err != nil {
   386  		t.Fatalf("should not have error: %s", err)
   387  	}
   388  }
   389  
   390  func TestBuilderPrepare_SSHPrivateKey(t *testing.T) {
   391  	var b Builder
   392  	config := testConfig()
   393  
   394  	config["ssh_private_key_file"] = ""
   395  	b = Builder{}
   396  	warns, err := b.Prepare(config)
   397  	if len(warns) > 0 {
   398  		t.Fatalf("bad: %#v", warns)
   399  	}
   400  	if err != nil {
   401  		t.Fatalf("should not have error: %s", err)
   402  	}
   403  
   404  	config["ssh_private_key_file"] = "/i/dont/exist"
   405  	b = Builder{}
   406  	warns, err = b.Prepare(config)
   407  	if len(warns) > 0 {
   408  		t.Fatalf("bad: %#v", warns)
   409  	}
   410  	if err == nil {
   411  		t.Fatal("should have error")
   412  	}
   413  
   414  	// Test bad contents
   415  	tf, err := ioutil.TempFile("", "packer")
   416  	if err != nil {
   417  		t.Fatalf("err: %s", err)
   418  	}
   419  	defer os.Remove(tf.Name())
   420  	defer tf.Close()
   421  
   422  	if _, err := tf.Write([]byte("HELLO!")); err != nil {
   423  		t.Fatalf("err: %s", err)
   424  	}
   425  
   426  	config["ssh_private_key_file"] = tf.Name()
   427  	b = Builder{}
   428  	warns, err = b.Prepare(config)
   429  	if len(warns) > 0 {
   430  		t.Fatalf("bad: %#v", warns)
   431  	}
   432  	if err == nil {
   433  		t.Fatal("should have error")
   434  	}
   435  
   436  	// Test good contents
   437  	tf.Seek(0, 0)
   438  	tf.Truncate(0)
   439  	tf.Write([]byte(testPem))
   440  	config["ssh_private_key_file"] = tf.Name()
   441  	b = Builder{}
   442  	warns, err = b.Prepare(config)
   443  	if len(warns) > 0 {
   444  		t.Fatalf("bad: %#v", warns)
   445  	}
   446  	if err != nil {
   447  		t.Fatalf("err: %s", err)
   448  	}
   449  }
   450  
   451  func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
   452  	var b Builder
   453  	config := testConfig()
   454  
   455  	// Test a default boot_wait
   456  	delete(config, "ssh_wait_timeout")
   457  	warns, err := b.Prepare(config)
   458  	if len(warns) > 0 {
   459  		t.Fatalf("bad: %#v", warns)
   460  	}
   461  	if err != nil {
   462  		t.Fatalf("err: %s", err)
   463  	}
   464  
   465  	// Test with a bad value
   466  	config["ssh_wait_timeout"] = "this is not good"
   467  	b = Builder{}
   468  	warns, err = b.Prepare(config)
   469  	if len(warns) > 0 {
   470  		t.Fatalf("bad: %#v", warns)
   471  	}
   472  	if err == nil {
   473  		t.Fatal("should have error")
   474  	}
   475  
   476  	// Test with a good one
   477  	config["ssh_wait_timeout"] = "5s"
   478  	b = Builder{}
   479  	warns, err = b.Prepare(config)
   480  	if len(warns) > 0 {
   481  		t.Fatalf("bad: %#v", warns)
   482  	}
   483  	if err != nil {
   484  		t.Fatalf("should not have error: %s", err)
   485  	}
   486  }
   487  
   488  func TestBuilderPrepare_QemuArgs(t *testing.T) {
   489  	var b Builder
   490  	config := testConfig()
   491  
   492  	// Test with empty
   493  	delete(config, "qemuargs")
   494  	warns, err := b.Prepare(config)
   495  	if len(warns) > 0 {
   496  		t.Fatalf("bad: %#v", warns)
   497  	}
   498  	if err != nil {
   499  		t.Fatalf("err: %s", err)
   500  	}
   501  
   502  	if !reflect.DeepEqual(b.config.QemuArgs, [][]string{}) {
   503  		t.Fatalf("bad: %#v", b.config.QemuArgs)
   504  	}
   505  
   506  	// Test with a good one
   507  	config["qemuargs"] = [][]interface{}{
   508  		{"foo", "bar", "baz"},
   509  	}
   510  
   511  	b = Builder{}
   512  	warns, err = b.Prepare(config)
   513  	if len(warns) > 0 {
   514  		t.Fatalf("bad: %#v", warns)
   515  	}
   516  	if err != nil {
   517  		t.Fatalf("should not have error: %s", err)
   518  	}
   519  
   520  	expected := [][]string{
   521  		{"foo", "bar", "baz"},
   522  	}
   523  
   524  	if !reflect.DeepEqual(b.config.QemuArgs, expected) {
   525  		t.Fatalf("bad: %#v", b.config.QemuArgs)
   526  	}
   527  }