From 031b20f197272d6ecad3085b82139d8ffbacce85 Mon Sep 17 00:00:00 2001 From: Jack Pearkes Date: Mon, 17 Jun 2013 14:21:15 +0200 Subject: [PATCH] builder/digitalocean: use text/template for the snapshot name --- builder/digitalocean/builder.go | 27 +++++++++++++++++++----- builder/digitalocean/builder_test.go | 30 +++++++++++++++++++++++---- builder/digitalocean/step_snapshot.go | 3 ++- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/builder/digitalocean/builder.go b/builder/digitalocean/builder.go index 5cb4cd6a2..d8469d752 100644 --- a/builder/digitalocean/builder.go +++ b/builder/digitalocean/builder.go @@ -4,6 +4,7 @@ package digitalocean import ( + "bytes" "errors" "fmt" "github.com/mitchellh/mapstructure" @@ -11,12 +12,18 @@ import ( "github.com/mitchellh/packer/builder/common" "github.com/mitchellh/packer/packer" "log" + "strconv" + "text/template" "time" ) // The unique id for the builder const BuilderId = "pearkes.digitalocean" +type snapshotNameData struct { + CreateTime string +} + // Configuration tells the builder the credentials // to use while communicating with DO and describes the image // you are creating @@ -27,7 +34,7 @@ type config struct { SizeID uint `mapstructure:"size_id"` ImageID uint `mapstructure:"image_id"` - SnapshotName string `mapstructure:"snapshot_name"` + SnapshotName string SSHUsername string `mapstructure:"ssh_username"` SSHPort uint `mapstructure:"ssh_port"` SSHTimeout time.Duration @@ -35,8 +42,9 @@ type config struct { PackerDebug bool `mapstructure:"packer_debug"` - RawSSHTimeout string `mapstructure:"ssh_timeout"` - RawEventDelay string `mapstructure:"event_delay"` + RawSnapshotName string `mapstructure:"snapshot_name"` + RawSSHTimeout string `mapstructure:"ssh_timeout"` + RawEventDelay string `mapstructure:"event_delay"` } type Builder struct { @@ -80,9 +88,9 @@ func (b *Builder) Prepare(raws ...interface{}) error { b.config.SSHPort = 22 } - if b.config.SnapshotName == "" { + if b.config.RawSnapshotName == "" { // Default to packer-{{ unix timestamp (utc) }} - b.config.SnapshotName = "packer-{{.CreateTime}}" + b.config.RawSnapshotName = "packer-{{.CreateTime}}" } if b.config.RawSSHTimeout == "" { @@ -121,6 +129,15 @@ func (b *Builder) Prepare(raws ...interface{}) error { } b.config.EventDelay = delay + // Parse the name of the snapshot + snapNameBuf := new(bytes.Buffer) + tData := snapshotNameData{ + strconv.FormatInt(time.Now().UTC().Unix(), 10), + } + t := template.Must(template.New("snapshot").Parse(b.config.RawSnapshotName)) + t.Execute(snapNameBuf, tData) + b.config.SnapshotName = snapNameBuf.String() + if len(errs) > 0 { return &packer.MultiError{errs} } diff --git a/builder/digitalocean/builder_test.go b/builder/digitalocean/builder_test.go index aba0bb1b7..907d5e7b4 100644 --- a/builder/digitalocean/builder_test.go +++ b/builder/digitalocean/builder_test.go @@ -2,6 +2,7 @@ package digitalocean import ( "github.com/mitchellh/packer/packer" + "strconv" "testing" ) @@ -256,14 +257,35 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { var b Builder config := testConfig() - // Test set - config["snapshot_name"] = "foo" + // Test default err := b.Prepare(config) if err != nil { t.Fatalf("should not have error: %s", err) } - if b.config.SnapshotName != "foo" { - t.Errorf("invalid: %s", b.config.SnapshotName) + if b.config.RawSnapshotName != "packer-{{.CreateTime}}" { + t.Errorf("invalid: %d", b.config.RawSnapshotName) } + + // Test set + config["snapshot_name"] = "foobarbaz" + b = Builder{} + err = b.Prepare(config) + if err != nil { + t.Fatalf("should not have error: %s", err) + } + + // Test set with template + config["snapshot_name"] = "{{.CreateTime}}" + b = Builder{} + err = b.Prepare(config) + if err != nil { + t.Fatalf("should not have error: %s", err) + } + + _, err = strconv.ParseInt(b.config.SnapshotName, 0, 0) + if err != nil { + t.Fatalf("failed to parse int in template: %s", err) + } + } diff --git a/builder/digitalocean/step_snapshot.go b/builder/digitalocean/step_snapshot.go index 93e450cf6..1abeb67b0 100644 --- a/builder/digitalocean/step_snapshot.go +++ b/builder/digitalocean/step_snapshot.go @@ -1,6 +1,7 @@ package digitalocean import ( + "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" ) @@ -13,7 +14,7 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction { c := state["config"].(config) dropletId := state["droplet_id"].(uint) - ui.Say("Creating snapshot...") + ui.Say(fmt.Sprintf("Creating snapshot: %v", c.SnapshotName)) err := client.CreateSnapshot(dropletId, c.SnapshotName)