github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/provisioner/puppet-masterless/provisioner_test.go (about)

     1  package puppetmasterless
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/hashicorp/packer/packer"
    12  	"github.com/hashicorp/packer/template/interpolate"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  func testConfig() map[string]interface{} {
    17  	tf, err := ioutil.TempFile("", "packer")
    18  	if err != nil {
    19  		panic(err)
    20  	}
    21  
    22  	return map[string]interface{}{
    23  		"manifest_file": tf.Name(),
    24  	}
    25  }
    26  
    27  func TestProvisioner_Impl(t *testing.T) {
    28  	var raw interface{}
    29  	raw = &Provisioner{}
    30  	if _, ok := raw.(packer.Provisioner); !ok {
    31  		t.Fatalf("must be a Provisioner")
    32  	}
    33  }
    34  
    35  func TestGuestOSConfig_empty_unix(t *testing.T) {
    36  	config := testConfig()
    37  	p := new(Provisioner)
    38  	err := p.Prepare(config)
    39  	if err != nil {
    40  		t.Fatalf("err: %s", err)
    41  	}
    42  	// Execute Puppet
    43  	p.config.ctx.Data = &ExecuteTemplate{
    44  		ManifestFile: "/r/m/f",
    45  		PuppetBinDir: p.config.PuppetBinDir,
    46  		Sudo:         !p.config.PreventSudo,
    47  		WorkingDir:   p.config.WorkingDir,
    48  	}
    49  	log.Println(p.config.ExecuteCommand)
    50  	command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
    51  	if err != nil {
    52  		t.Fatalf("err: %s", err)
    53  	}
    54  
    55  	expected := "cd /tmp/packer-puppet-masterless && " +
    56  		"sudo -E puppet apply --verbose --modulepath='' --detailed-exitcodes /r/m/f"
    57  	assert.Equal(t, expected, command)
    58  }
    59  
    60  func TestGuestOSConfig_full_unix(t *testing.T) {
    61  	config := testConfig()
    62  	p := new(Provisioner)
    63  	err := p.Prepare(config)
    64  	if err != nil {
    65  		t.Fatalf("err: %s", err)
    66  	}
    67  
    68  	facterVars := []string{
    69  		fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, "lhs", "rhs"),
    70  		fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, "foo", "bar"),
    71  	}
    72  	modulePaths := []string{"/m/p", "/a/b"}
    73  	// Execute Puppet
    74  	p.config.ctx.Data = &ExecuteTemplate{
    75  		FacterVars:      strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
    76  		HieraConfigPath: "/h/c/p",
    77  		ManifestDir:     "/r/m/d",
    78  		ManifestFile:    "/r/m/f",
    79  		ModulePath:      strings.Join(modulePaths, p.guestOSTypeConfig.modulePathJoiner),
    80  		PuppetBinDir:    p.config.PuppetBinDir,
    81  		Sudo:            !p.config.PreventSudo,
    82  		WorkingDir:      p.config.WorkingDir,
    83  		ExtraArguments:  strings.Join(p.config.ExtraArguments, " "),
    84  	}
    85  	command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
    86  	if err != nil {
    87  		t.Fatalf("err: %s", err)
    88  	}
    89  
    90  	expected := "cd /tmp/packer-puppet-masterless && FACTER_lhs='rhs' FACTER_foo='bar' " +
    91  		"sudo -E puppet apply " +
    92  		"--verbose --modulepath='/m/p:/a/b' --hiera_config='/h/c/p' " +
    93  		"--manifestdir='/r/m/d' --detailed-exitcodes /r/m/f"
    94  	assert.Equal(t, expected, command)
    95  }
    96  
    97  func TestGuestOSConfig_empty_windows(t *testing.T) {
    98  	config := testConfig()
    99  	config["guest_os_type"] = "windows"
   100  	p := new(Provisioner)
   101  	err := p.Prepare(config)
   102  	if err != nil {
   103  		t.Fatalf("err: %s", err)
   104  	}
   105  	// Execute Puppet
   106  	p.config.ctx.Data = &ExecuteTemplate{
   107  		ManifestFile: "/r/m/f",
   108  		PuppetBinDir: p.config.PuppetBinDir,
   109  		Sudo:         !p.config.PreventSudo,
   110  		WorkingDir:   p.config.WorkingDir,
   111  	}
   112  	log.Println(p.config.ExecuteCommand)
   113  	command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
   114  	if err != nil {
   115  		t.Fatalf("err: %s", err)
   116  	}
   117  
   118  	expected := "cd C:/Windows/Temp/packer-puppet-masterless &&  && puppet apply --verbose --modulepath='' --detailed-exitcodes /r/m/f"
   119  	assert.Equal(t, expected, command)
   120  }
   121  
   122  func TestGuestOSConfig_full_windows(t *testing.T) {
   123  	config := testConfig()
   124  	config["guest_os_type"] = "windows"
   125  	p := new(Provisioner)
   126  	err := p.Prepare(config)
   127  	if err != nil {
   128  		t.Fatalf("err: %s", err)
   129  	}
   130  
   131  	facterVars := []string{
   132  		fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, "lhs", "rhs"),
   133  		fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, "foo", "bar"),
   134  	}
   135  	modulePaths := []string{"/m/p", "/a/b"}
   136  	// Execute Puppet
   137  	p.config.ctx.Data = &ExecuteTemplate{
   138  		FacterVars:      strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
   139  		HieraConfigPath: "/h/c/p",
   140  		ManifestDir:     "/r/m/d",
   141  		ManifestFile:    "/r/m/f",
   142  		ModulePath:      strings.Join(modulePaths, p.guestOSTypeConfig.modulePathJoiner),
   143  		PuppetBinDir:    p.config.PuppetBinDir,
   144  		Sudo:            !p.config.PreventSudo,
   145  		WorkingDir:      p.config.WorkingDir,
   146  		ExtraArguments:  strings.Join(p.config.ExtraArguments, " "),
   147  	}
   148  	command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
   149  	if err != nil {
   150  		t.Fatalf("err: %s", err)
   151  	}
   152  
   153  	expected := "cd C:/Windows/Temp/packer-puppet-masterless && " +
   154  		"SET \"FACTER_lhs=rhs\" & SET \"FACTER_foo=bar\" && " +
   155  		"puppet apply --verbose --modulepath='/m/p;/a/b' --hiera_config='/h/c/p' " +
   156  		"--manifestdir='/r/m/d' --detailed-exitcodes /r/m/f"
   157  	assert.Equal(t, expected, command)
   158  }
   159  
   160  func TestProvisionerPrepare_puppetBinDir(t *testing.T) {
   161  	config := testConfig()
   162  
   163  	delete(config, "puppet_bin_dir")
   164  	p := new(Provisioner)
   165  	err := p.Prepare(config)
   166  	if err != nil {
   167  		t.Fatalf("err: %s", err)
   168  	}
   169  
   170  	// Test with a good one
   171  	tf, err := ioutil.TempFile("", "packer")
   172  	if err != nil {
   173  		t.Fatalf("error tempfile: %s", err)
   174  	}
   175  	defer os.Remove(tf.Name())
   176  
   177  	config["puppet_bin_dir"] = tf.Name()
   178  	p = new(Provisioner)
   179  	err = p.Prepare(config)
   180  	if err != nil {
   181  		t.Fatalf("err: %s", err)
   182  	}
   183  }
   184  
   185  func TestProvisionerPrepare_hieraConfigPath(t *testing.T) {
   186  	config := testConfig()
   187  
   188  	delete(config, "hiera_config_path")
   189  	p := new(Provisioner)
   190  	err := p.Prepare(config)
   191  	if err != nil {
   192  		t.Fatalf("err: %s", err)
   193  	}
   194  
   195  	// Test with a good one
   196  	tf, err := ioutil.TempFile("", "packer")
   197  	if err != nil {
   198  		t.Fatalf("error tempfile: %s", err)
   199  	}
   200  	defer os.Remove(tf.Name())
   201  
   202  	config["hiera_config_path"] = tf.Name()
   203  	p = new(Provisioner)
   204  	err = p.Prepare(config)
   205  	if err != nil {
   206  		t.Fatalf("err: %s", err)
   207  	}
   208  }
   209  
   210  func TestProvisionerPrepare_manifestFile(t *testing.T) {
   211  	config := testConfig()
   212  
   213  	delete(config, "manifest_file")
   214  	p := new(Provisioner)
   215  	err := p.Prepare(config)
   216  	if err == nil {
   217  		t.Fatal("should be an error")
   218  	}
   219  
   220  	// Test with a good one
   221  	tf, err := ioutil.TempFile("", "packer")
   222  	if err != nil {
   223  		t.Fatalf("error tempfile: %s", err)
   224  	}
   225  	defer os.Remove(tf.Name())
   226  
   227  	config["manifest_file"] = tf.Name()
   228  	p = new(Provisioner)
   229  	err = p.Prepare(config)
   230  	if err != nil {
   231  		t.Fatalf("err: %s", err)
   232  	}
   233  }
   234  
   235  func TestProvisionerPrepare_manifestDir(t *testing.T) {
   236  	config := testConfig()
   237  
   238  	delete(config, "manifestdir")
   239  	p := new(Provisioner)
   240  	err := p.Prepare(config)
   241  	if err != nil {
   242  		t.Fatalf("err: %s", err)
   243  	}
   244  
   245  	// Test with a good one
   246  	td, err := ioutil.TempDir("", "packer")
   247  	if err != nil {
   248  		t.Fatalf("error: %s", err)
   249  	}
   250  	defer os.RemoveAll(td)
   251  
   252  	config["manifest_dir"] = td
   253  	p = new(Provisioner)
   254  	err = p.Prepare(config)
   255  	if err != nil {
   256  		t.Fatalf("err: %s", err)
   257  	}
   258  }
   259  
   260  func TestProvisionerPrepare_modulePaths(t *testing.T) {
   261  	config := testConfig()
   262  
   263  	delete(config, "module_paths")
   264  	p := new(Provisioner)
   265  	err := p.Prepare(config)
   266  	if err != nil {
   267  		t.Fatalf("err: %s", err)
   268  	}
   269  
   270  	// Test with bad paths
   271  	config["module_paths"] = []string{"i-should-not-exist"}
   272  	p = new(Provisioner)
   273  	err = p.Prepare(config)
   274  	if err == nil {
   275  		t.Fatal("should be an error")
   276  	}
   277  
   278  	// Test with a good one
   279  	td, err := ioutil.TempDir("", "packer")
   280  	if err != nil {
   281  		t.Fatalf("error: %s", err)
   282  	}
   283  	defer os.RemoveAll(td)
   284  
   285  	config["module_paths"] = []string{td}
   286  	p = new(Provisioner)
   287  	err = p.Prepare(config)
   288  	if err != nil {
   289  		t.Fatalf("err: %s", err)
   290  	}
   291  }
   292  
   293  func TestProvisionerPrepare_facterFacts(t *testing.T) {
   294  	config := testConfig()
   295  
   296  	delete(config, "facter")
   297  	p := new(Provisioner)
   298  	err := p.Prepare(config)
   299  	if err != nil {
   300  		t.Fatalf("err: %s", err)
   301  	}
   302  
   303  	// Test with malformed fact
   304  	config["facter"] = "fact=stringified"
   305  	p = new(Provisioner)
   306  	err = p.Prepare(config)
   307  	if err == nil {
   308  		t.Fatal("should be an error")
   309  	}
   310  
   311  	// Test with a good one
   312  	td, err := ioutil.TempDir("", "packer")
   313  	if err != nil {
   314  		t.Fatalf("error: %s", err)
   315  	}
   316  	defer os.RemoveAll(td)
   317  
   318  	facts := make(map[string]string)
   319  	facts["fact_name"] = "fact_value"
   320  	config["facter"] = facts
   321  
   322  	p = new(Provisioner)
   323  	err = p.Prepare(config)
   324  	if err != nil {
   325  		t.Fatalf("err: %s", err)
   326  	}
   327  
   328  	// Make sure the default facts are present
   329  	delete(config, "facter")
   330  	p = new(Provisioner)
   331  	err = p.Prepare(config)
   332  	if err != nil {
   333  		t.Fatalf("err: %s", err)
   334  	}
   335  	if p.config.Facter == nil {
   336  		t.Fatalf("err: Default facts are not set in the Puppet provisioner!")
   337  	}
   338  
   339  	if _, ok := p.config.Facter["packer_build_name"]; !ok {
   340  		t.Fatalf("err: packer_build_name fact not set in the Puppet provisioner!")
   341  	}
   342  
   343  	if _, ok := p.config.Facter["packer_builder_type"]; !ok {
   344  		t.Fatalf("err: packer_builder_type fact not set in the Puppet provisioner!")
   345  	}
   346  }
   347  
   348  func TestProvisionerPrepare_extraArguments(t *testing.T) {
   349  	config := testConfig()
   350  
   351  	// Test with missing parameter
   352  	delete(config, "extra_arguments")
   353  	p := new(Provisioner)
   354  	err := p.Prepare(config)
   355  	if err != nil {
   356  		t.Fatalf("err: %s", err)
   357  	}
   358  
   359  	// Test with malformed value
   360  	config["extra_arguments"] = "{{}}"
   361  	p = new(Provisioner)
   362  	err = p.Prepare(config)
   363  	if err == nil {
   364  		t.Fatal("should be an error")
   365  	}
   366  
   367  	// Test with valid values
   368  	config["extra_arguments"] = []string{
   369  		"arg",
   370  	}
   371  
   372  	p = new(Provisioner)
   373  	err = p.Prepare(config)
   374  	if err != nil {
   375  		t.Fatalf("err: %s", err)
   376  	}
   377  }
   378  
   379  func TestProvisionerPrepare_stagingDir(t *testing.T) {
   380  	config := testConfig()
   381  
   382  	delete(config, "staging_directory")
   383  	p := new(Provisioner)
   384  	err := p.Prepare(config)
   385  	if err != nil {
   386  		t.Fatalf("err: %s", err)
   387  	}
   388  
   389  	// Make sure the default staging directory is correct
   390  	if p.config.StagingDir != "/tmp/packer-puppet-masterless" {
   391  		t.Fatalf("err: Default staging_directory is not set in the Puppet provisioner!")
   392  	}
   393  
   394  	// Make sure default staging directory can be overridden
   395  	config["staging_directory"] = "/tmp/override"
   396  	p = new(Provisioner)
   397  	err = p.Prepare(config)
   398  	if err != nil {
   399  		t.Fatalf("err: %s", err)
   400  	}
   401  
   402  	if p.config.StagingDir != "/tmp/override" {
   403  		t.Fatalf("err: Overridden staging_directory is not set correctly in the Puppet provisioner!")
   404  	}
   405  }
   406  
   407  func TestProvisionerPrepare_workingDir(t *testing.T) {
   408  	config := testConfig()
   409  
   410  	delete(config, "working_directory")
   411  	p := new(Provisioner)
   412  	err := p.Prepare(config)
   413  	if err != nil {
   414  		t.Fatalf("err: %s", err)
   415  	}
   416  
   417  	// Make sure default working dir and staging dir are the same
   418  	if p.config.WorkingDir != p.config.StagingDir {
   419  		t.Fatalf("err: Default working_directory is not set to the same value as default staging_directory in the Puppet provisioner!")
   420  	}
   421  
   422  	// Make sure the default working directory is correct
   423  	if p.config.WorkingDir != "/tmp/packer-puppet-masterless" {
   424  		t.Fatalf("err: Default working_directory is not set in the Puppet provisioner!")
   425  	}
   426  
   427  	// Make sure default working directory can be overridden
   428  	config["working_directory"] = "/tmp/override"
   429  	p = new(Provisioner)
   430  	err = p.Prepare(config)
   431  	if err != nil {
   432  		t.Fatalf("err: %s", err)
   433  	}
   434  
   435  	if p.config.WorkingDir != "/tmp/override" {
   436  		t.Fatalf("err: Overridden working_directory is not set correctly in the Puppet provisioner!")
   437  	}
   438  }
   439  
   440  func TestProvisionerProvision_extraArguments(t *testing.T) {
   441  	config := testConfig()
   442  	ui := &packer.MachineReadableUi{
   443  		Writer: ioutil.Discard,
   444  	}
   445  	comm := new(packer.MockCommunicator)
   446  
   447  	extraArguments := []string{
   448  		"--some-arg=yup",
   449  		"--some-other-arg",
   450  	}
   451  	config["extra_arguments"] = extraArguments
   452  
   453  	// Test with valid values
   454  	p := new(Provisioner)
   455  	err := p.Prepare(config)
   456  	if err != nil {
   457  		t.Fatalf("err: %s", err)
   458  	}
   459  
   460  	err = p.Provision(ui, comm)
   461  	if err != nil {
   462  		t.Fatalf("err: %s", err)
   463  	}
   464  
   465  	expectedArgs := strings.Join(extraArguments, " ")
   466  
   467  	if !strings.Contains(comm.StartCmd.Command, expectedArgs) {
   468  		t.Fatalf("Command %q doesn't contain the expected arguments %q", comm.StartCmd.Command, expectedArgs)
   469  	}
   470  
   471  	// Test with missing parameter
   472  	delete(config, "extra_arguments")
   473  
   474  	p = new(Provisioner)
   475  	err = p.Prepare(config)
   476  	if err != nil {
   477  		t.Fatalf("err: %s", err)
   478  	}
   479  
   480  	err = p.Provision(ui, comm)
   481  	if err != nil {
   482  		t.Fatalf("err: %s", err)
   483  	}
   484  
   485  	// Check the expected `extra_arguments` position for an empty value
   486  	splitCommand := strings.Split(comm.StartCmd.Command, " ")
   487  	if "" == splitCommand[len(splitCommand)-2] {
   488  		t.Fatalf("Command %q contains an extra-space which may cause arg parsing issues", comm.StartCmd.Command)
   489  	}
   490  }