2015-05-08 23:25:24 +02:00
|
|
|
package chef
|
2015-05-08 13:45:31 +02:00
|
|
|
|
|
|
|
import (
|
2015-07-10 12:56:27 +02:00
|
|
|
"fmt"
|
|
|
|
"path"
|
2015-05-08 13:45:31 +02:00
|
|
|
"testing"
|
|
|
|
|
2015-05-08 18:17:57 +02:00
|
|
|
"github.com/hashicorp/terraform/communicator"
|
2015-05-08 13:45:31 +02:00
|
|
|
"github.com/hashicorp/terraform/config"
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestResourceProvisioner_impl(t *testing.T) {
|
|
|
|
var _ terraform.ResourceProvisioner = new(ResourceProvisioner)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_Validate_good(t *testing.T) {
|
|
|
|
c := testConfig(t, map[string]interface{}{
|
2016-09-15 14:20:18 +02:00
|
|
|
"environment": "_default",
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2015-05-08 13:45:31 +02:00
|
|
|
})
|
2015-05-08 18:17:57 +02:00
|
|
|
r := new(ResourceProvisioner)
|
|
|
|
warn, errs := r.Validate(c)
|
2015-05-08 13:45:31 +02:00
|
|
|
if len(warn) > 0 {
|
|
|
|
t.Fatalf("Warnings: %v", warn)
|
|
|
|
}
|
|
|
|
if len(errs) > 0 {
|
|
|
|
t.Fatalf("Errors: %v", errs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_Validate_bad(t *testing.T) {
|
|
|
|
c := testConfig(t, map[string]interface{}{
|
2015-05-08 18:17:57 +02:00
|
|
|
"invalid": "nope",
|
2015-05-08 13:45:31 +02:00
|
|
|
})
|
|
|
|
p := new(ResourceProvisioner)
|
|
|
|
warn, errs := p.Validate(c)
|
|
|
|
if len(warn) > 0 {
|
|
|
|
t.Fatalf("Warnings: %v", warn)
|
|
|
|
}
|
|
|
|
if len(errs) == 0 {
|
|
|
|
t.Fatalf("Should have errors")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-29 21:30:44 +01:00
|
|
|
// Test that the JSON attributes with an unknown value don't
|
|
|
|
// validate.
|
|
|
|
func TestResourceProvider_Validate_computedValues(t *testing.T) {
|
|
|
|
c := testConfig(t, map[string]interface{}{
|
|
|
|
"environment": "_default",
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
|
|
|
"attributes_json": config.UnknownVariableValue,
|
|
|
|
})
|
|
|
|
r := new(ResourceProvisioner)
|
|
|
|
warn, errs := r.Validate(c)
|
|
|
|
if len(warn) > 0 {
|
|
|
|
t.Fatalf("Warnings: %v", warn)
|
|
|
|
}
|
|
|
|
if len(errs) > 0 {
|
|
|
|
t.Fatalf("Errors: %v", errs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-08 13:45:31 +02:00
|
|
|
func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig {
|
|
|
|
r, err := config.NewRawConfig(c)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return terraform.NewResourceConfig(r)
|
|
|
|
}
|
2015-05-08 18:17:57 +02:00
|
|
|
|
|
|
|
func TestResourceProvider_runChefClient(t *testing.T) {
|
|
|
|
cases := map[string]struct {
|
|
|
|
Config *terraform.ResourceConfig
|
2015-07-10 12:56:27 +02:00
|
|
|
ChefCmd string
|
2015-05-08 18:17:57 +02:00
|
|
|
ConfDir string
|
|
|
|
Commands map[string]bool
|
|
|
|
}{
|
|
|
|
"Sudo": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
2016-09-15 14:20:18 +02:00
|
|
|
"node_name": "nodename1",
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2015-05-08 18:17:57 +02:00
|
|
|
}),
|
|
|
|
|
2015-07-10 12:56:27 +02:00
|
|
|
ChefCmd: linuxChefCmd,
|
|
|
|
|
2015-05-08 18:17:57 +02:00
|
|
|
ConfDir: linuxConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
2015-07-10 12:56:27 +02:00
|
|
|
fmt.Sprintf(`sudo %s -j %q -E "_default"`,
|
|
|
|
linuxChefCmd,
|
|
|
|
path.Join(linuxConfDir, "first-boot.json")): true,
|
2015-05-08 18:17:57 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"NoSudo": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
2016-09-15 14:20:18 +02:00
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2015-05-08 18:17:57 +02:00
|
|
|
}),
|
|
|
|
|
2015-07-10 12:56:27 +02:00
|
|
|
ChefCmd: linuxChefCmd,
|
|
|
|
|
2015-05-08 18:17:57 +02:00
|
|
|
ConfDir: linuxConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
2015-07-10 12:56:27 +02:00
|
|
|
fmt.Sprintf(`%s -j %q -E "_default"`,
|
|
|
|
linuxChefCmd,
|
|
|
|
path.Join(linuxConfDir, "first-boot.json")): true,
|
2015-05-08 18:17:57 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"Environment": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
2016-09-15 14:20:18 +02:00
|
|
|
"environment": "production",
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2015-05-08 18:17:57 +02:00
|
|
|
}),
|
|
|
|
|
2015-07-10 12:56:27 +02:00
|
|
|
ChefCmd: windowsChefCmd,
|
|
|
|
|
2015-05-08 18:17:57 +02:00
|
|
|
ConfDir: windowsConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
2015-07-10 12:56:27 +02:00
|
|
|
fmt.Sprintf(`%s -j %q -E "production"`,
|
|
|
|
windowsChefCmd,
|
|
|
|
path.Join(windowsConfDir, "first-boot.json")): true,
|
2015-05-08 18:17:57 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
r := new(ResourceProvisioner)
|
|
|
|
o := new(terraform.MockUIOutput)
|
|
|
|
c := new(communicator.MockCommunicator)
|
|
|
|
|
|
|
|
for k, tc := range cases {
|
|
|
|
c.Commands = tc.Commands
|
|
|
|
|
|
|
|
p, err := r.decodeConfig(tc.Config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:56:27 +02:00
|
|
|
p.runChefClient = p.runChefClientFunc(tc.ChefCmd, tc.ConfDir)
|
2015-05-12 10:37:38 +02:00
|
|
|
p.useSudo = !p.PreventSudo
|
2015-05-08 18:17:57 +02:00
|
|
|
|
|
|
|
err = p.runChefClient(o, c)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Test %q failed: %v", k, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-04 15:31:24 +01:00
|
|
|
|
|
|
|
func TestResourceProvider_fetchChefCertificates(t *testing.T) {
|
|
|
|
cases := map[string]struct {
|
|
|
|
Config *terraform.ResourceConfig
|
|
|
|
KnifeCmd string
|
|
|
|
ConfDir string
|
|
|
|
Commands map[string]bool
|
|
|
|
}{
|
|
|
|
"Sudo": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"fetch_chef_certificates": true,
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
2016-09-15 14:20:18 +02:00
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2016-02-04 15:31:24 +01:00
|
|
|
}),
|
|
|
|
|
|
|
|
KnifeCmd: linuxKnifeCmd,
|
|
|
|
|
|
|
|
ConfDir: linuxConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf(`sudo %s ssl fetch -c %s`,
|
|
|
|
linuxKnifeCmd,
|
|
|
|
path.Join(linuxConfDir, "client.rb")): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"NoSudo": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"fetch_chef_certificates": true,
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
2016-09-15 14:20:18 +02:00
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
2016-02-04 15:31:24 +01:00
|
|
|
}),
|
|
|
|
|
|
|
|
KnifeCmd: windowsKnifeCmd,
|
|
|
|
|
|
|
|
ConfDir: windowsConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf(`%s ssl fetch -c %s`,
|
|
|
|
windowsKnifeCmd,
|
|
|
|
path.Join(windowsConfDir, "client.rb")): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
r := new(ResourceProvisioner)
|
|
|
|
o := new(terraform.MockUIOutput)
|
|
|
|
c := new(communicator.MockCommunicator)
|
|
|
|
|
|
|
|
for k, tc := range cases {
|
|
|
|
c.Commands = tc.Commands
|
|
|
|
|
|
|
|
p, err := r.decodeConfig(tc.Config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
p.fetchChefCertificates = p.fetchChefCertificatesFunc(tc.KnifeCmd, tc.ConfDir)
|
|
|
|
p.useSudo = !p.PreventSudo
|
|
|
|
|
|
|
|
err = p.fetchChefCertificates(o, c)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Test %q failed: %v", k, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-01 00:35:27 +02:00
|
|
|
|
|
|
|
func TestResourceProvider_configureVaults(t *testing.T) {
|
|
|
|
cases := map[string]struct {
|
|
|
|
Config *terraform.ResourceConfig
|
|
|
|
GemCmd string
|
|
|
|
KnifeCmd string
|
|
|
|
ConfDir string
|
|
|
|
Commands map[string]bool
|
|
|
|
}{
|
|
|
|
"Linux Vault string": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
|
|
|
"vault_json": `{"vault1": "item1"}`,
|
|
|
|
}),
|
|
|
|
|
|
|
|
GemCmd: linuxGemCmd,
|
|
|
|
KnifeCmd: linuxKnifeCmd,
|
|
|
|
ConfDir: linuxConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf("%s install chef-vault", linuxGemCmd): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"Linux Vault []string": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"fetch_chef_certificates": true,
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
|
|
|
"vault_json": `{"vault1": ["item1", "item2"]}`,
|
|
|
|
}),
|
|
|
|
|
|
|
|
GemCmd: linuxGemCmd,
|
|
|
|
KnifeCmd: linuxKnifeCmd,
|
|
|
|
ConfDir: linuxConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf("%s install chef-vault", linuxGemCmd): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item2 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"Windows Vault string": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
|
|
|
"vault_json": `{"vault1": "item1"}`,
|
|
|
|
}),
|
|
|
|
|
|
|
|
GemCmd: windowsGemCmd,
|
|
|
|
KnifeCmd: windowsKnifeCmd,
|
|
|
|
ConfDir: windowsConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf("%s install chef-vault", windowsGemCmd): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
"Windows Vault []string": {
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"fetch_chef_certificates": true,
|
|
|
|
"node_name": "nodename1",
|
|
|
|
"prevent_sudo": true,
|
|
|
|
"run_list": []interface{}{"cookbook::recipe"},
|
|
|
|
"server_url": "https://chef.local",
|
|
|
|
"user_name": "bob",
|
|
|
|
"user_key": "USER-KEY",
|
|
|
|
"vault_json": `{"vault1": ["item1", "item2"]}`,
|
|
|
|
}),
|
|
|
|
|
|
|
|
GemCmd: windowsGemCmd,
|
|
|
|
KnifeCmd: windowsKnifeCmd,
|
|
|
|
ConfDir: windowsConfDir,
|
|
|
|
|
|
|
|
Commands: map[string]bool{
|
|
|
|
fmt.Sprintf("%s install chef-vault", windowsGemCmd): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
|
|
|
|
fmt.Sprintf("%s vault update vault1 item2 -A nodename1 -M client -c %s/client.rb "+
|
|
|
|
"-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
r := new(ResourceProvisioner)
|
|
|
|
o := new(terraform.MockUIOutput)
|
|
|
|
c := new(communicator.MockCommunicator)
|
|
|
|
|
|
|
|
for k, tc := range cases {
|
|
|
|
c.Commands = tc.Commands
|
|
|
|
|
|
|
|
p, err := r.decodeConfig(tc.Config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Error: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
p.configureVaults = p.configureVaultsFunc(tc.GemCmd, tc.KnifeCmd, tc.ConfDir)
|
|
|
|
p.useSudo = !p.PreventSudo
|
|
|
|
|
|
|
|
err = p.configureVaults(o, c)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Test %q failed: %v", k, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|