#348: chef-solo provisioner: add support for data_bags and roles

This commit is contained in:
Jerry Clinesmith 2013-09-10 22:00:29 -05:00
parent 3163d785c8
commit fa2f277c67
2 changed files with 82 additions and 4 deletions

View File

@ -18,6 +18,8 @@ type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
CookbookPaths []string `mapstructure:"cookbook_paths"` CookbookPaths []string `mapstructure:"cookbook_paths"`
RolesPath string `mapstructure:"roles_path"`
DataBagsPath string `mapstructure:"data_bags_path"`
ExecuteCommand string `mapstructure:"execute_command"` ExecuteCommand string `mapstructure:"execute_command"`
InstallCommand string `mapstructure:"install_command"` InstallCommand string `mapstructure:"install_command"`
RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"` RemoteCookbookPaths []string `mapstructure:"remote_cookbook_paths"`
@ -36,6 +38,8 @@ type Provisioner struct {
type ConfigTemplate struct { type ConfigTemplate struct {
CookbookPaths string CookbookPaths string
RolesPath string
DataBagsPath string
} }
type ExecuteTemplate struct { type ExecuteTemplate struct {
@ -130,6 +134,24 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
} }
} }
if p.config.RolesPath != "" {
pFileInfo, err := os.Stat(p.config.RolesPath)
if err != nil || !pFileInfo.IsDir() {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Bad roles path '%s': %s", p.config.RolesPath, err))
}
}
if p.config.DataBagsPath != "" {
pFileInfo, err := os.Stat(p.config.DataBagsPath)
if err != nil || !pFileInfo.IsDir() {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Bad data bags path '%s': %s", p.config.DataBagsPath, err))
}
}
// Process the user variables within the JSON and set the JSON. // Process the user variables within the JSON and set the JSON.
// Do this early so that we can validate and show errors. // Do this early so that we can validate and show errors.
p.config.Json, err = p.processJsonUserVars() p.config.Json, err = p.processJsonUserVars()
@ -166,7 +188,23 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
cookbookPaths = append(cookbookPaths, targetPath) cookbookPaths = append(cookbookPaths, targetPath)
} }
configPath, err := p.createConfig(ui, comm, cookbookPaths) rolesPath := ""
if p.config.RolesPath != "" {
rolesPath := fmt.Sprintf("%s/roles", p.config.StagingDir)
if err := p.uploadDirectory(ui, comm, rolesPath, p.config.RolesPath); err != nil {
return fmt.Errorf("Error uploading roles: %s", err)
}
}
dataBagsPath := ""
if p.config.DataBagsPath != "" {
dataBagsPath := fmt.Sprintf("%s/data_bags", p.config.StagingDir)
if err := p.uploadDirectory(ui, comm, dataBagsPath, p.config.DataBagsPath); err != nil {
return fmt.Errorf("Error uploading data bags: %s", err)
}
}
configPath, err := p.createConfig(ui, comm, cookbookPaths, rolesPath, dataBagsPath)
if err != nil { if err != nil {
return fmt.Errorf("Error creating Chef config file: %s", err) return fmt.Errorf("Error creating Chef config file: %s", err)
} }
@ -203,7 +241,7 @@ func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, ds
return comm.UploadDir(dst, src, nil) return comm.UploadDir(dst, src, nil)
} }
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string) (string, error) { func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, localCookbooks []string, rolesPath string, dataBagsPath string) (string, error) {
ui.Message("Creating configuration file 'solo.rb'") ui.Message("Creating configuration file 'solo.rb'")
cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks)) cookbook_paths := make([]string, len(p.config.RemoteCookbookPaths)+len(localCookbooks))
@ -216,8 +254,20 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local
cookbook_paths[i] = fmt.Sprintf(`"%s"`, path) cookbook_paths[i] = fmt.Sprintf(`"%s"`, path)
} }
roles_path := ""
if rolesPath != "" {
roles_path = fmt.Sprintf(`"%s"`, rolesPath)
}
data_bags_path := ""
if dataBagsPath != "" {
data_bags_path = fmt.Sprintf(`"%s"`, dataBagsPath)
}
configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{ configString, err := p.config.tpl.Process(DefaultConfigTemplate, &ConfigTemplate{
CookbookPaths: strings.Join(cookbook_paths, ","), CookbookPaths: strings.Join(cookbook_paths, ","),
RolesPath: roles_path,
DataBagsPath: data_bags_path,
}) })
if err != nil { if err != nil {
return "", err return "", err
@ -369,4 +419,10 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) {
var DefaultConfigTemplate = ` var DefaultConfigTemplate = `
cookbook_path [{{.CookbookPaths}}] cookbook_path [{{.CookbookPaths}}]
{{if .RolesPath != ""}}
role_path {{.RolesPath}}
{{end}}
{{if .DataBagsPath != ""}}
data_bag_path {{.DataBagsPath}}
{{end}}
` `

View File

@ -32,11 +32,25 @@ func TestProvisionerPrepare_cookbookPaths(t *testing.T) {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
rolesPath, err := ioutil.TempDir("", "roles")
if err != nil {
t.Fatalf("err: %s", err)
}
dataBagsPath, err := ioutil.TempDir("", "data_bags")
if err != nil {
t.Fatalf("err: %s", err)
}
defer os.Remove(path1) defer os.Remove(path1)
defer os.Remove(path2) defer os.Remove(path2)
defer os.Remove(rolesPath)
defer os.Remove(dataBagsPath)
config := testConfig() config := testConfig()
config["cookbook_paths"] = []string{path1, path2} config["cookbook_paths"] = []string{path1, path2}
config["roles_path"] = rolesPath
config["data_bags_path"] = dataBagsPath
err = p.Prepare(config) err = p.Prepare(config)
if err != nil { if err != nil {
@ -50,6 +64,14 @@ func TestProvisionerPrepare_cookbookPaths(t *testing.T) {
if p.config.CookbookPaths[0] != path1 || p.config.CookbookPaths[1] != path2 { if p.config.CookbookPaths[0] != path1 || p.config.CookbookPaths[1] != path2 {
t.Fatalf("unexpected: %#v", p.config.CookbookPaths) t.Fatalf("unexpected: %#v", p.config.CookbookPaths)
} }
if p.config.RolesPath != rolesPath {
t.Fatalf("unexpected: %#v", p.config.RolesPath)
}
if p.config.DataBagsPath != dataBagsPath {
t.Fatalf("unexpected: %#v", p.config.DataBagsPath)
}
} }
func TestProvisionerPrepare_json(t *testing.T) { func TestProvisionerPrepare_json(t *testing.T) {