From 587f057bf6ec7a31fdd6905f2f7fb606bd24fb77 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 13 Dec 2013 18:30:57 -0800 Subject: [PATCH] builder/googlecompute: StepUploadImage --- builder/googlecompute/builder.go | 2 +- builder/googlecompute/step_upload_image.go | 29 +++--- .../googlecompute/step_upload_image_test.go | 88 +++++++++++++++++++ 3 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 builder/googlecompute/step_upload_image_test.go diff --git a/builder/googlecompute/builder.go b/builder/googlecompute/builder.go index 6f823a4e9..3cbab24a5 100644 --- a/builder/googlecompute/builder.go +++ b/builder/googlecompute/builder.go @@ -60,9 +60,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe new(common.StepProvision), new(StepUpdateGsutil), new(StepCreateImage), + new(StepUploadImage), } /* - new(stepUploadImage), new(stepRegisterImage), }*/ diff --git a/builder/googlecompute/step_upload_image.go b/builder/googlecompute/step_upload_image.go index 956b981bc..45505f20b 100644 --- a/builder/googlecompute/step_upload_image.go +++ b/builder/googlecompute/step_upload_image.go @@ -7,34 +7,39 @@ import ( "github.com/mitchellh/packer/packer" ) -// stepUploadImage represents a Packer build step that uploads GCE machine images. -type stepUploadImage int +// StepUploadImage represents a Packer build step that uploads GCE machine images. +type StepUploadImage int // Run executes the Packer build step that uploads a GCE machine image. -func (s *stepUploadImage) Run(state multistep.StateBag) multistep.StepAction { - var ( - config = state.Get("config").(*Config) - comm = state.Get("communicator").(packer.Communicator) - sudoPrefix = "" - ui = state.Get("ui").(packer.Ui) - imageFilename = state.Get("image_file_name").(string) - ) - ui.Say("Uploading image...") +func (s *StepUploadImage) Run(state multistep.StateBag) multistep.StepAction { + comm := state.Get("communicator").(packer.Communicator) + config := state.Get("config").(*Config) + imageFilename := state.Get("image_file_name").(string) + ui := state.Get("ui").(packer.Ui) + + sudoPrefix := "" if config.SSHUsername != "root" { sudoPrefix = "sudo " } + + ui.Say("Uploading image...") cmd := new(packer.RemoteCmd) cmd.Command = fmt.Sprintf("%s/usr/local/bin/gsutil cp %s gs://%s", sudoPrefix, imageFilename, config.BucketName) err := cmd.StartWithUi(comm, ui) + if err == nil && cmd.ExitStatus != 0 { + err = fmt.Errorf( + "gsutil exited with non-zero exit status: %d", cmd.ExitStatus) + } if err != nil { err := fmt.Errorf("Error uploading image: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } + return multistep.ActionContinue } // Cleanup. -func (s *stepUploadImage) Cleanup(state multistep.StateBag) {} +func (s *StepUploadImage) Cleanup(state multistep.StateBag) {} diff --git a/builder/googlecompute/step_upload_image_test.go b/builder/googlecompute/step_upload_image_test.go new file mode 100644 index 000000000..54be445fc --- /dev/null +++ b/builder/googlecompute/step_upload_image_test.go @@ -0,0 +1,88 @@ +package googlecompute + +import ( + "strings" + "testing" + + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" +) + +func TestStepUploadImage_impl(t *testing.T) { + var _ multistep.Step = new(StepUploadImage) +} + +func TestStepUploadImage(t *testing.T) { + state := testState(t) + step := new(StepUploadImage) + defer step.Cleanup(state) + + comm := new(packer.MockCommunicator) + state.Put("communicator", comm) + state.Put("image_file_name", "foo") + + // run the step + if action := step.Run(state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + + // Verify + if !comm.StartCalled { + t.Fatal("start should be called") + } + if strings.HasPrefix(comm.StartCmd.Command, "sudo") { + t.Fatal("should not sudo") + } + if !strings.Contains(comm.StartCmd.Command, "gsutil cp") { + t.Fatalf("bad command: %#v", comm.StartCmd.Command) + } +} + +func TestStepUploadImage_badExitStatus(t *testing.T) { + state := testState(t) + step := new(StepUploadImage) + defer step.Cleanup(state) + + comm := new(packer.MockCommunicator) + comm.StartExitStatus = 12 + state.Put("communicator", comm) + state.Put("image_file_name", "foo") + + // run the step + if action := step.Run(state); action != multistep.ActionHalt { + t.Fatalf("bad action: %#v", action) + } + + if _, ok := state.GetOk("error"); !ok { + t.Fatal("should have error") + } +} + +func TestStepUploadImage_nonRoot(t *testing.T) { + state := testState(t) + step := new(StepUploadImage) + defer step.Cleanup(state) + + comm := new(packer.MockCommunicator) + state.Put("communicator", comm) + state.Put("image_file_name", "foo") + + config := state.Get("config").(*Config) + config.SSHUsername = "bob" + + // run the step + if action := step.Run(state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + + // Verify + if !comm.StartCalled { + t.Fatal("start should be called") + } + if !strings.HasPrefix(comm.StartCmd.Command, "sudo") { + t.Fatal("should sudo") + } + if !strings.Contains(comm.StartCmd.Command, "gsutil cp") { + t.Fatalf("bad command: %#v", comm.StartCmd.Command) + } +}