From 343c594bb3638ea5e8caced27765ce5df3806a96 Mon Sep 17 00:00:00 2001 From: Michael Nikitochkin Date: Wed, 28 Sep 2016 15:00:57 +0200 Subject: [PATCH] Added UserDataFile support for DigitalOcean builder config. --- builder/digitalocean/builder_acc_test.go | 4 +++- builder/digitalocean/config.go | 11 +++++++++++ builder/digitalocean/step_create_droplet.go | 15 ++++++++++++++- website/source/docs/builders/digitalocean.html.md | 3 +++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/builder/digitalocean/builder_acc_test.go b/builder/digitalocean/builder_acc_test.go index f9df863cb..4e7931ade 100644 --- a/builder/digitalocean/builder_acc_test.go +++ b/builder/digitalocean/builder_acc_test.go @@ -27,7 +27,9 @@ const testBuilderAccBasic = ` "type": "test", "region": "nyc2", "size": "512mb", - "image": "ubuntu-12-04-x64" + "image": "ubuntu-12-04-x64", + "user_date": "", + "user_date_file": "" }] } ` diff --git a/builder/digitalocean/config.go b/builder/digitalocean/config.go index a32970f40..0474c8b13 100644 --- a/builder/digitalocean/config.go +++ b/builder/digitalocean/config.go @@ -31,6 +31,7 @@ type Config struct { StateTimeout time.Duration `mapstructure:"state_timeout"` DropletName string `mapstructure:"droplet_name"` UserData string `mapstructure:"user_data"` + UserDataFile string `mapstructure:"user_data_file"` ctx interpolate.Context } @@ -113,6 +114,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs, errors.New("image is required")) } + if c.UserData != "" && c.UserDataFile != "" { + errs = packer.MultiErrorAppend( + errs, errors.New("only one of user_data or user_data_file can be specified")) + } else if c.UserDataFile != "" { + if _, err := os.Stat(c.UserDataFile); err != nil { + errs = packer.MultiErrorAppend( + errs, errors.New(fmt.Sprintf("user_data_file not found: %s", c.UserDataFile))) + } + } + if errs != nil && len(errs.Errors) > 0 { return nil, nil, errs } diff --git a/builder/digitalocean/step_create_droplet.go b/builder/digitalocean/step_create_droplet.go index aafd53622..45d6db9da 100644 --- a/builder/digitalocean/step_create_droplet.go +++ b/builder/digitalocean/step_create_droplet.go @@ -6,6 +6,7 @@ import ( "github.com/digitalocean/godo" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + "io/ioutil" ) type stepCreateDroplet struct { @@ -20,6 +21,18 @@ func (s *stepCreateDroplet) Run(state multistep.StateBag) multistep.StepAction { // Create the droplet based on configuration ui.Say("Creating droplet...") + + userData := c.UserData + if c.UserDataFile != "" { + contents, err := ioutil.ReadFile(c.UserDataFile) + if err != nil { + state.Put("error", fmt.Errorf("Problem reading user data file: %s", err)) + return multistep.ActionHalt + } + + userData = string(contents) + } + droplet, _, err := client.Droplets.Create(&godo.DropletCreateRequest{ Name: c.DropletName, Region: c.Region, @@ -31,7 +44,7 @@ func (s *stepCreateDroplet) Run(state multistep.StateBag) multistep.StepAction { godo.DropletCreateSSHKey{ID: int(sshKeyId)}, }, PrivateNetworking: c.PrivateNetworking, - UserData: c.UserData, + UserData: userData, }) if err != nil { err := fmt.Errorf("Error creating droplet: %s", err) diff --git a/website/source/docs/builders/digitalocean.html.md b/website/source/docs/builders/digitalocean.html.md index 6aef71ee7..d25f94bbf 100644 --- a/website/source/docs/builders/digitalocean.html.md +++ b/website/source/docs/builders/digitalocean.html.md @@ -75,6 +75,9 @@ builder. default state timeout is "6m". - `user_data` (string) - User data to launch with the Droplet. +- `user_data_file` (string) - Path to a file that will be used for the user + data when launching the Droplet. + ## Basic Example