github.com/Hashicorp/terraform@v0.11.12-beta1/builtin/provisioners/chef/resource_provisioner_test.go (about)

     1  package chef
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/communicator"
     9  	"github.com/hashicorp/terraform/config"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  func TestResourceProvisioner_impl(t *testing.T) {
    15  	var _ terraform.ResourceProvisioner = Provisioner()
    16  }
    17  
    18  func TestProvisioner(t *testing.T) {
    19  	if err := Provisioner().(*schema.Provisioner).InternalValidate(); err != nil {
    20  		t.Fatalf("err: %s", err)
    21  	}
    22  }
    23  
    24  func TestResourceProvider_Validate_good(t *testing.T) {
    25  	c := testConfig(t, map[string]interface{}{
    26  		"environment": "_default",
    27  		"node_name":   "nodename1",
    28  		"run_list":    []interface{}{"cookbook::recipe"},
    29  		"server_url":  "https://chef.local",
    30  		"user_name":   "bob",
    31  		"user_key":    "USER-KEY",
    32  	})
    33  
    34  	warn, errs := Provisioner().Validate(c)
    35  	if len(warn) > 0 {
    36  		t.Fatalf("Warnings: %v", warn)
    37  	}
    38  	if len(errs) > 0 {
    39  		t.Fatalf("Errors: %v", errs)
    40  	}
    41  }
    42  
    43  func TestResourceProvider_Validate_bad(t *testing.T) {
    44  	c := testConfig(t, map[string]interface{}{
    45  		"invalid": "nope",
    46  	})
    47  
    48  	warn, errs := Provisioner().Validate(c)
    49  	if len(warn) > 0 {
    50  		t.Fatalf("Warnings: %v", warn)
    51  	}
    52  	if len(errs) == 0 {
    53  		t.Fatalf("Should have errors")
    54  	}
    55  }
    56  
    57  // Test that the JSON attributes with an unknown value don't
    58  // validate.
    59  func TestResourceProvider_Validate_computedValues(t *testing.T) {
    60  	c := testConfig(t, map[string]interface{}{
    61  		"environment":     "_default",
    62  		"node_name":       "nodename1",
    63  		"run_list":        []interface{}{"cookbook::recipe"},
    64  		"server_url":      "https://chef.local",
    65  		"user_name":       "bob",
    66  		"user_key":        "USER-KEY",
    67  		"attributes_json": config.UnknownVariableValue,
    68  	})
    69  
    70  	warn, errs := Provisioner().Validate(c)
    71  	if len(warn) > 0 {
    72  		t.Fatalf("Warnings: %v", warn)
    73  	}
    74  	if len(errs) > 0 {
    75  		t.Fatalf("Errors: %v", errs)
    76  	}
    77  }
    78  
    79  func TestResourceProvider_runChefClient(t *testing.T) {
    80  	cases := map[string]struct {
    81  		Config   map[string]interface{}
    82  		ChefCmd  string
    83  		ConfDir  string
    84  		Commands map[string]bool
    85  	}{
    86  		"Sudo": {
    87  			Config: map[string]interface{}{
    88  				"node_name":  "nodename1",
    89  				"run_list":   []interface{}{"cookbook::recipe"},
    90  				"server_url": "https://chef.local",
    91  				"user_name":  "bob",
    92  				"user_key":   "USER-KEY",
    93  			},
    94  
    95  			ChefCmd: linuxChefCmd,
    96  
    97  			ConfDir: linuxConfDir,
    98  
    99  			Commands: map[string]bool{
   100  				fmt.Sprintf(`sudo %s -j %q -E "_default"`,
   101  					linuxChefCmd,
   102  					path.Join(linuxConfDir, "first-boot.json")): true,
   103  			},
   104  		},
   105  
   106  		"NoSudo": {
   107  			Config: map[string]interface{}{
   108  				"node_name":    "nodename1",
   109  				"prevent_sudo": true,
   110  				"run_list":     []interface{}{"cookbook::recipe"},
   111  				"server_url":   "https://chef.local",
   112  				"user_name":    "bob",
   113  				"user_key":     "USER-KEY",
   114  			},
   115  
   116  			ChefCmd: linuxChefCmd,
   117  
   118  			ConfDir: linuxConfDir,
   119  
   120  			Commands: map[string]bool{
   121  				fmt.Sprintf(`%s -j %q -E "_default"`,
   122  					linuxChefCmd,
   123  					path.Join(linuxConfDir, "first-boot.json")): true,
   124  			},
   125  		},
   126  
   127  		"Environment": {
   128  			Config: map[string]interface{}{
   129  				"environment":  "production",
   130  				"node_name":    "nodename1",
   131  				"prevent_sudo": true,
   132  				"run_list":     []interface{}{"cookbook::recipe"},
   133  				"server_url":   "https://chef.local",
   134  				"user_name":    "bob",
   135  				"user_key":     "USER-KEY",
   136  			},
   137  
   138  			ChefCmd: windowsChefCmd,
   139  
   140  			ConfDir: windowsConfDir,
   141  
   142  			Commands: map[string]bool{
   143  				fmt.Sprintf(`%s -j %q -E "production"`,
   144  					windowsChefCmd,
   145  					path.Join(windowsConfDir, "first-boot.json")): true,
   146  			},
   147  		},
   148  	}
   149  
   150  	o := new(terraform.MockUIOutput)
   151  	c := new(communicator.MockCommunicator)
   152  
   153  	for k, tc := range cases {
   154  		c.Commands = tc.Commands
   155  
   156  		p, err := decodeConfig(
   157  			schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
   158  		)
   159  		if err != nil {
   160  			t.Fatalf("Error: %v", err)
   161  		}
   162  
   163  		p.runChefClient = p.runChefClientFunc(tc.ChefCmd, tc.ConfDir)
   164  		p.useSudo = !p.PreventSudo
   165  
   166  		err = p.runChefClient(o, c)
   167  		if err != nil {
   168  			t.Fatalf("Test %q failed: %v", k, err)
   169  		}
   170  	}
   171  }
   172  
   173  func TestResourceProvider_fetchChefCertificates(t *testing.T) {
   174  	cases := map[string]struct {
   175  		Config   map[string]interface{}
   176  		KnifeCmd string
   177  		ConfDir  string
   178  		Commands map[string]bool
   179  	}{
   180  		"Sudo": {
   181  			Config: map[string]interface{}{
   182  				"fetch_chef_certificates": true,
   183  				"node_name":               "nodename1",
   184  				"run_list":                []interface{}{"cookbook::recipe"},
   185  				"server_url":              "https://chef.local",
   186  				"user_name":               "bob",
   187  				"user_key":                "USER-KEY",
   188  			},
   189  
   190  			KnifeCmd: linuxKnifeCmd,
   191  
   192  			ConfDir: linuxConfDir,
   193  
   194  			Commands: map[string]bool{
   195  				fmt.Sprintf(`sudo %s ssl fetch -c %s`,
   196  					linuxKnifeCmd,
   197  					path.Join(linuxConfDir, "client.rb")): true,
   198  			},
   199  		},
   200  
   201  		"NoSudo": {
   202  			Config: map[string]interface{}{
   203  				"fetch_chef_certificates": true,
   204  				"node_name":               "nodename1",
   205  				"prevent_sudo":            true,
   206  				"run_list":                []interface{}{"cookbook::recipe"},
   207  				"server_url":              "https://chef.local",
   208  				"user_name":               "bob",
   209  				"user_key":                "USER-KEY",
   210  			},
   211  
   212  			KnifeCmd: windowsKnifeCmd,
   213  
   214  			ConfDir: windowsConfDir,
   215  
   216  			Commands: map[string]bool{
   217  				fmt.Sprintf(`%s ssl fetch -c %s`,
   218  					windowsKnifeCmd,
   219  					path.Join(windowsConfDir, "client.rb")): true,
   220  			},
   221  		},
   222  	}
   223  
   224  	o := new(terraform.MockUIOutput)
   225  	c := new(communicator.MockCommunicator)
   226  
   227  	for k, tc := range cases {
   228  		c.Commands = tc.Commands
   229  
   230  		p, err := decodeConfig(
   231  			schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
   232  		)
   233  		if err != nil {
   234  			t.Fatalf("Error: %v", err)
   235  		}
   236  
   237  		p.fetchChefCertificates = p.fetchChefCertificatesFunc(tc.KnifeCmd, tc.ConfDir)
   238  		p.useSudo = !p.PreventSudo
   239  
   240  		err = p.fetchChefCertificates(o, c)
   241  		if err != nil {
   242  			t.Fatalf("Test %q failed: %v", k, err)
   243  		}
   244  	}
   245  }
   246  
   247  func TestResourceProvider_configureVaults(t *testing.T) {
   248  	cases := map[string]struct {
   249  		Config   map[string]interface{}
   250  		GemCmd   string
   251  		KnifeCmd string
   252  		ConfDir  string
   253  		Commands map[string]bool
   254  	}{
   255  		"Linux Vault string": {
   256  			Config: map[string]interface{}{
   257  				"node_name":    "nodename1",
   258  				"prevent_sudo": true,
   259  				"run_list":     []interface{}{"cookbook::recipe"},
   260  				"server_url":   "https://chef.local",
   261  				"user_name":    "bob",
   262  				"user_key":     "USER-KEY",
   263  				"vault_json":   `{"vault1": "item1"}`,
   264  			},
   265  
   266  			GemCmd:   linuxGemCmd,
   267  			KnifeCmd: linuxKnifeCmd,
   268  			ConfDir:  linuxConfDir,
   269  
   270  			Commands: map[string]bool{
   271  				fmt.Sprintf("%s install chef-vault", linuxGemCmd): true,
   272  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   273  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   274  			},
   275  		},
   276  
   277  		"Linux Vault []string": {
   278  			Config: map[string]interface{}{
   279  				"fetch_chef_certificates": true,
   280  				"node_name":               "nodename1",
   281  				"prevent_sudo":            true,
   282  				"run_list":                []interface{}{"cookbook::recipe"},
   283  				"server_url":              "https://chef.local",
   284  				"user_name":               "bob",
   285  				"user_key":                "USER-KEY",
   286  				"vault_json":              `{"vault1": ["item1", "item2"]}`,
   287  			},
   288  
   289  			GemCmd:   linuxGemCmd,
   290  			KnifeCmd: linuxKnifeCmd,
   291  			ConfDir:  linuxConfDir,
   292  
   293  			Commands: map[string]bool{
   294  				fmt.Sprintf("%s install chef-vault", linuxGemCmd): true,
   295  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   296  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   297  				fmt.Sprintf("%s vault update vault1 item2 -C nodename1 -M client -c %s/client.rb "+
   298  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   299  			},
   300  		},
   301  
   302  		"Linux Vault []string (recreate-client for vault)": {
   303  			Config: map[string]interface{}{
   304  				"fetch_chef_certificates": true,
   305  				"node_name":               "nodename1",
   306  				"prevent_sudo":            true,
   307  				"run_list":                []interface{}{"cookbook::recipe"},
   308  				"server_url":              "https://chef.local",
   309  				"user_name":               "bob",
   310  				"user_key":                "USER-KEY",
   311  				"vault_json":              `{"vault1": ["item1", "item2"]}`,
   312  				"recreate_client":         true,
   313  			},
   314  
   315  			GemCmd:   linuxGemCmd,
   316  			KnifeCmd: linuxKnifeCmd,
   317  			ConfDir:  linuxConfDir,
   318  
   319  			Commands: map[string]bool{
   320  				fmt.Sprintf("%s install chef-vault", linuxGemCmd): true,
   321  				fmt.Sprintf("%s vault remove vault1 item1 -C \"nodename1\" -M client -c %s/client.rb "+
   322  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   323  				fmt.Sprintf("%s vault remove vault1 item2 -C \"nodename1\" -M client -c %s/client.rb "+
   324  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   325  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   326  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   327  				fmt.Sprintf("%s vault update vault1 item2 -C nodename1 -M client -c %s/client.rb "+
   328  					"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
   329  			},
   330  		},
   331  
   332  		"Windows Vault string": {
   333  			Config: map[string]interface{}{
   334  				"node_name":    "nodename1",
   335  				"prevent_sudo": true,
   336  				"run_list":     []interface{}{"cookbook::recipe"},
   337  				"server_url":   "https://chef.local",
   338  				"user_name":    "bob",
   339  				"user_key":     "USER-KEY",
   340  				"vault_json":   `{"vault1": "item1"}`,
   341  			},
   342  
   343  			GemCmd:   windowsGemCmd,
   344  			KnifeCmd: windowsKnifeCmd,
   345  			ConfDir:  windowsConfDir,
   346  
   347  			Commands: map[string]bool{
   348  				fmt.Sprintf("%s install chef-vault", windowsGemCmd): true,
   349  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   350  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   351  			},
   352  		},
   353  
   354  		"Windows Vault []string": {
   355  			Config: map[string]interface{}{
   356  				"fetch_chef_certificates": true,
   357  				"node_name":               "nodename1",
   358  				"prevent_sudo":            true,
   359  				"run_list":                []interface{}{"cookbook::recipe"},
   360  				"server_url":              "https://chef.local",
   361  				"user_name":               "bob",
   362  				"user_key":                "USER-KEY",
   363  				"vault_json":              `{"vault1": ["item1", "item2"]}`,
   364  			},
   365  
   366  			GemCmd:   windowsGemCmd,
   367  			KnifeCmd: windowsKnifeCmd,
   368  			ConfDir:  windowsConfDir,
   369  
   370  			Commands: map[string]bool{
   371  				fmt.Sprintf("%s install chef-vault", windowsGemCmd): true,
   372  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   373  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   374  				fmt.Sprintf("%s vault update vault1 item2 -C nodename1 -M client -c %s/client.rb "+
   375  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   376  			},
   377  		},
   378  
   379  		"Windows Vault [] string (recreate-client for vault)": {
   380  			Config: map[string]interface{}{
   381  				"fetch_chef_certificates": true,
   382  				"node_name":               "nodename1",
   383  				"prevent_sudo":            true,
   384  				"run_list":                []interface{}{"cookbook::recipe"},
   385  				"server_url":              "https://chef.local",
   386  				"user_name":               "bob",
   387  				"user_key":                "USER-KEY",
   388  				"vault_json":              `{"vault1": ["item1", "item2"]}`,
   389  				"recreate_client":         true,
   390  			},
   391  
   392  			GemCmd:   windowsGemCmd,
   393  			KnifeCmd: windowsKnifeCmd,
   394  			ConfDir:  windowsConfDir,
   395  
   396  			Commands: map[string]bool{
   397  				fmt.Sprintf("%s install chef-vault", windowsGemCmd): true,
   398  				fmt.Sprintf("%s vault remove vault1 item1 -C \"nodename1\" -M client -c %s/client.rb "+
   399  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   400  				fmt.Sprintf("%s vault remove vault1 item2 -C \"nodename1\" -M client -c %s/client.rb "+
   401  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   402  				fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+
   403  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   404  				fmt.Sprintf("%s vault update vault1 item2 -C nodename1 -M client -c %s/client.rb "+
   405  					"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
   406  			},
   407  		},
   408  	}
   409  
   410  	o := new(terraform.MockUIOutput)
   411  	c := new(communicator.MockCommunicator)
   412  
   413  	for k, tc := range cases {
   414  		c.Commands = tc.Commands
   415  
   416  		p, err := decodeConfig(
   417  			schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config),
   418  		)
   419  		if err != nil {
   420  			t.Fatalf("Error: %v", err)
   421  		}
   422  
   423  		p.configureVaults = p.configureVaultsFunc(tc.GemCmd, tc.KnifeCmd, tc.ConfDir)
   424  		p.useSudo = !p.PreventSudo
   425  
   426  		err = p.configureVaults(o, c)
   427  		if err != nil {
   428  			t.Fatalf("Test %q failed: %v", k, err)
   429  		}
   430  	}
   431  }
   432  
   433  func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig {
   434  	r, err := config.NewRawConfig(c)
   435  	if err != nil {
   436  		t.Fatalf("bad: %s", err)
   437  	}
   438  
   439  	return terraform.NewResourceConfig(r)
   440  }