builder/digitalocean: add configurable "event_delay" for sleeps
This commit is contained in:
parent
c12e9ff9a8
commit
1e17e90acd
|
@ -31,10 +31,12 @@ type config struct {
|
||||||
SSHUsername string `mapstructure:"ssh_username"`
|
SSHUsername string `mapstructure:"ssh_username"`
|
||||||
SSHPort uint `mapstructure:"ssh_port"`
|
SSHPort uint `mapstructure:"ssh_port"`
|
||||||
SSHTimeout time.Duration
|
SSHTimeout time.Duration
|
||||||
|
EventDelay time.Duration
|
||||||
|
|
||||||
PackerDebug bool `mapstructure:"packer_debug"`
|
PackerDebug bool `mapstructure:"packer_debug"`
|
||||||
|
|
||||||
RawSSHTimeout string `mapstructure:"ssh_timeout"`
|
RawSSHTimeout string `mapstructure:"ssh_timeout"`
|
||||||
|
RawEventDelay string `mapstructure:"event_delay"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
|
@ -88,6 +90,12 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
b.config.RawSSHTimeout = "1m"
|
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
|
// A list of errors on the configuration
|
||||||
errs := make([]error, 0)
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
@ -100,12 +108,19 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
if b.config.APIKey == "" {
|
if b.config.APIKey == "" {
|
||||||
errs = append(errs, errors.New("an api_key must be specified"))
|
errs = append(errs, errors.New("an api_key must be specified"))
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout, err := time.ParseDuration(b.config.RawSSHTimeout)
|
timeout, err := time.ParseDuration(b.config.RawSSHTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err))
|
errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err))
|
||||||
}
|
}
|
||||||
b.config.SSHTimeout = timeout
|
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 {
|
if len(errs) > 0 {
|
||||||
return &packer.MultiError{errs}
|
return &packer.MultiError{errs}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
func TestBuilderPrepare_SnapshotName(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ func (s *stepCreateDroplet) Cleanup(state map[string]interface{}) {
|
||||||
|
|
||||||
client := state["client"].(*DigitalOceanClient)
|
client := state["client"].(*DigitalOceanClient)
|
||||||
ui := state["ui"].(packer.Ui)
|
ui := state["ui"].(packer.Ui)
|
||||||
|
c := state["config"].(config)
|
||||||
|
|
||||||
// Destroy the droplet we just created
|
// Destroy the droplet we just created
|
||||||
ui.Say("Destroying droplet...")
|
ui.Say("Destroying droplet...")
|
||||||
|
@ -56,7 +58,8 @@ func (s *stepCreateDroplet) Cleanup(state map[string]interface{}) {
|
||||||
// Sleep arbitrarily before sending destroy request
|
// Sleep arbitrarily before sending destroy request
|
||||||
// Otherwise we get "pending event" errors, even though there isn't
|
// Otherwise we get "pending event" errors, even though there isn't
|
||||||
// one.
|
// one.
|
||||||
time.Sleep(5 * time.Second)
|
log.Printf("Sleeping for %v, event_delay", c.RawEventDelay)
|
||||||
|
time.Sleep(c.EventDelay)
|
||||||
|
|
||||||
err := client.DestroyDroplet(s.dropletId)
|
err := client.DestroyDroplet(s.dropletId)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package digitalocean
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,13 +11,15 @@ type stepPowerOff struct{}
|
||||||
|
|
||||||
func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction {
|
func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction {
|
||||||
client := state["client"].(*DigitalOceanClient)
|
client := state["client"].(*DigitalOceanClient)
|
||||||
|
c := state["config"].(config)
|
||||||
ui := state["ui"].(packer.Ui)
|
ui := state["ui"].(packer.Ui)
|
||||||
dropletId := state["droplet_id"].(uint)
|
dropletId := state["droplet_id"].(uint)
|
||||||
|
|
||||||
// Sleep arbitrarily before sending power off request
|
// Sleep arbitrarily before sending power off request
|
||||||
// Otherwise we get "pending event" errors, even though there isn't
|
// Otherwise we get "pending event" errors, even though there isn't
|
||||||
// one.
|
// 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
|
// Poweroff the droplet so it can be snapshot
|
||||||
err := client.PowerOffDroplet(dropletId)
|
err := client.PowerOffDroplet(dropletId)
|
||||||
|
|
Loading…
Reference in New Issue