github.com/lymingtonprecision/terraform@v0.9.9-0.20170613092852-62acef9611a9/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 "Windows Vault string": { 303 Config: map[string]interface{}{ 304 "node_name": "nodename1", 305 "prevent_sudo": true, 306 "run_list": []interface{}{"cookbook::recipe"}, 307 "server_url": "https://chef.local", 308 "user_name": "bob", 309 "user_key": "USER-KEY", 310 "vault_json": `{"vault1": "item1"}`, 311 }, 312 313 GemCmd: windowsGemCmd, 314 KnifeCmd: windowsKnifeCmd, 315 ConfDir: windowsConfDir, 316 317 Commands: map[string]bool{ 318 fmt.Sprintf("%s install chef-vault", windowsGemCmd): true, 319 fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+ 320 "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, 321 }, 322 }, 323 324 "Windows Vault []string": { 325 Config: map[string]interface{}{ 326 "fetch_chef_certificates": true, 327 "node_name": "nodename1", 328 "prevent_sudo": true, 329 "run_list": []interface{}{"cookbook::recipe"}, 330 "server_url": "https://chef.local", 331 "user_name": "bob", 332 "user_key": "USER-KEY", 333 "vault_json": `{"vault1": ["item1", "item2"]}`, 334 }, 335 336 GemCmd: windowsGemCmd, 337 KnifeCmd: windowsKnifeCmd, 338 ConfDir: windowsConfDir, 339 340 Commands: map[string]bool{ 341 fmt.Sprintf("%s install chef-vault", windowsGemCmd): true, 342 fmt.Sprintf("%s vault update vault1 item1 -C nodename1 -M client -c %s/client.rb "+ 343 "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, 344 fmt.Sprintf("%s vault update vault1 item2 -C nodename1 -M client -c %s/client.rb "+ 345 "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, 346 }, 347 }, 348 } 349 350 o := new(terraform.MockUIOutput) 351 c := new(communicator.MockCommunicator) 352 353 for k, tc := range cases { 354 c.Commands = tc.Commands 355 356 p, err := decodeConfig( 357 schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, tc.Config), 358 ) 359 if err != nil { 360 t.Fatalf("Error: %v", err) 361 } 362 363 p.configureVaults = p.configureVaultsFunc(tc.GemCmd, tc.KnifeCmd, tc.ConfDir) 364 p.useSudo = !p.PreventSudo 365 366 err = p.configureVaults(o, c) 367 if err != nil { 368 t.Fatalf("Test %q failed: %v", k, err) 369 } 370 } 371 } 372 373 func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig { 374 r, err := config.NewRawConfig(c) 375 if err != nil { 376 t.Fatalf("bad: %s", err) 377 } 378 379 return terraform.NewResourceConfig(r) 380 }