builder/digitalocean: add configurable "event_delay" for sleeps

This commit is contained in:
Jack Pearkes 2013-06-17 13:28:21 +02:00
parent c12e9ff9a8
commit 1e17e90acd
4 changed files with 55 additions and 2 deletions

View File

@ -31,10 +31,12 @@ type config struct {
SSHUsername string `mapstructure:"ssh_username"`
SSHPort uint `mapstructure:"ssh_port"`
SSHTimeout time.Duration
EventDelay time.Duration
PackerDebug bool `mapstructure:"packer_debug"`
RawSSHTimeout string `mapstructure:"ssh_timeout"`
RawEventDelay string `mapstructure:"event_delay"`
}
type Builder struct {
@ -88,6 +90,12 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.RawSSHTimeout = "1m"
}
if b.config.RawEventDelay == "" {
// Default to 5 second delays after creating events
// to allow DO to process
b.config.RawEventDelay = "5s"
}
// A list of errors on the configuration
errs := make([]error, 0)
@ -100,12 +108,19 @@ func (b *Builder) Prepare(raws ...interface{}) error {
if b.config.APIKey == "" {
errs = append(errs, errors.New("an api_key must be specified"))
}
timeout, err := time.ParseDuration(b.config.RawSSHTimeout)
if err != nil {
errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err))
}
b.config.SSHTimeout = timeout
delay, err := time.ParseDuration(b.config.RawEventDelay)
if err != nil {
errs = append(errs, fmt.Errorf("Failed parsing event_delay: %s", err))
}
b.config.EventDelay = delay
if len(errs) > 0 {
return &packer.MultiError{errs}
}

View File

@ -220,6 +220,38 @@ func TestBuilderPrepare_SSHTimeout(t *testing.T) {
}
func TestBuilderPrepare_EventDelay(t *testing.T) {
var b Builder
config := testConfig()
// Test default
err := b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if b.config.RawEventDelay != "5s" {
t.Errorf("invalid: %d", b.config.RawEventDelay)
}
// Test set
config["event_delay"] = "10s"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
// Test bad
config["event_delay"] = "tubes"
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
}
func TestBuilderPrepare_SnapshotName(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -6,6 +6,7 @@ import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"time"
)
@ -49,6 +50,7 @@ func (s *stepCreateDroplet) Cleanup(state map[string]interface{}) {
client := state["client"].(*DigitalOceanClient)
ui := state["ui"].(packer.Ui)
c := state["config"].(config)
// Destroy the droplet we just created
ui.Say("Destroying droplet...")
@ -56,7 +58,8 @@ func (s *stepCreateDroplet) Cleanup(state map[string]interface{}) {
// Sleep arbitrarily before sending destroy request
// Otherwise we get "pending event" errors, even though there isn't
// one.
time.Sleep(5 * time.Second)
log.Printf("Sleeping for %v, event_delay", c.RawEventDelay)
time.Sleep(c.EventDelay)
err := client.DestroyDroplet(s.dropletId)

View File

@ -3,6 +3,7 @@ package digitalocean
import (
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"time"
)
@ -10,13 +11,15 @@ type stepPowerOff struct{}
func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction {
client := state["client"].(*DigitalOceanClient)
c := state["config"].(config)
ui := state["ui"].(packer.Ui)
dropletId := state["droplet_id"].(uint)
// Sleep arbitrarily before sending power off request
// Otherwise we get "pending event" errors, even though there isn't
// one.
time.Sleep(3 * time.Second)
log.Printf("Sleeping for %v, event_delay", c.RawEventDelay)
time.Sleep(c.EventDelay)
// Poweroff the droplet so it can be snapshot
err := client.PowerOffDroplet(dropletId)