diff --git a/builder/oracle/classic/builder.go b/builder/oracle/classic/builder.go index 0106d96f7..5cbc07f40 100644 --- a/builder/oracle/classic/builder.go +++ b/builder/oracle/classic/builder.go @@ -121,10 +121,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Host: ocommon.CommHost, SSHConfig: b.config.Comm.SSHConfigFunc(), }, - &stepCreateImage{ + &stepUploadImage{ uploadImageCommand: b.config.BuilderUploadImageCommand, - imageName: b.config.ImageName, }, + &stepCreateImage{}, &stepListImages{}, &common.StepCleanupTempKeys{ Comm: &b.config.Comm, diff --git a/builder/oracle/classic/pv_config.go b/builder/oracle/classic/pv_config.go index e335371b3..300c5393e 100644 --- a/builder/oracle/classic/pv_config.go +++ b/builder/oracle/classic/pv_config.go @@ -18,6 +18,7 @@ type PVConfig struct { */ } +// IsPV tells us if we're using a persistent volume for this build func (c *PVConfig) IsPV() bool { return c.PersistentVolumeSize > 0 } diff --git a/builder/oracle/classic/step_create_image.go b/builder/oracle/classic/step_create_image.go index 2c3a221ac..6d32a23a7 100644 --- a/builder/oracle/classic/step_create_image.go +++ b/builder/oracle/classic/step_create_image.go @@ -4,83 +4,20 @@ import ( "context" "fmt" "log" - "strings" "github.com/hashicorp/go-oracle-terraform/compute" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" - "github.com/hashicorp/packer/template/interpolate" ) type stepCreateImage struct { - uploadImageCommand string - imageName string -} - -type uploadCmdData struct { - Username string - Password string - AccountID string - ImageFile string - SegmentPath string } func (s *stepCreateImage) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - //hook := state.Get("hook").(packer.Hook) ui := state.Get("ui").(packer.Ui) - comm := state.Get("communicator").(packer.Communicator) client := state.Get("client").(*compute.ComputeClient) config := state.Get("config").(*Config) - runID := state.Get("run_id").(string) - - imageFile := fmt.Sprintf("%s.tar.gz", s.imageName) - - config.ctx.Data = uploadCmdData{ - Username: config.Username, - Password: config.Password, - AccountID: config.IdentityDomain, - ImageFile: imageFile, - SegmentPath: fmt.Sprintf("compute_images_segments/%s/_segment_/%s", imageFile, runID), - } - uploadImageCmd, err := interpolate.Render(s.uploadImageCommand, &config.ctx) - if err != nil { - err := fmt.Errorf("Error processing image upload command: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - command := fmt.Sprintf(`#!/bin/sh - set -e - set -x - mkdir /builder - mkfs -t ext3 /dev/xvdb - mount /dev/xvdb /builder - chown opc:opc /builder - cd /builder - dd if=/dev/xvdc bs=8M status=progress | cp --sparse=always /dev/stdin diskimage.raw - tar czSf ./diskimage.tar.gz ./diskimage.raw - rm diskimage.raw - %s`, uploadImageCmd) - - dest := "/tmp/create-packer-diskimage.sh" - comm.Upload(dest, strings.NewReader(command), nil) - cmd := &packer.RemoteCmd{ - Command: fmt.Sprintf("sudo /bin/sh %s", dest), - } - if err := cmd.StartWithUi(comm, ui); err != nil { - err = fmt.Errorf("Problem creating image`: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - if cmd.ExitStatus != 0 { - err = fmt.Errorf("Create Disk Image command failed with exit code %d", cmd.ExitStatus) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } + imageFile := state.Get("image_file").(string) // Image uploaded, let's register it machineImageClient := client.MachineImages() @@ -89,7 +26,7 @@ func (s *stepCreateImage) Run(_ context.Context, state multistep.StateBag) multi Account: fmt.Sprintf("/Compute-%s/cloud_storage", config.IdentityDomain), Description: "Packer generated TODO", // The three-part name of the object - Name: s.imageName, + Name: config.ImageName, // image_file.tar.gz, where image_file is the .tar.gz name of the machine image file that you have uploaded to Oracle Cloud Infrastructure Object Storage Classic. File: imageFile, } @@ -128,11 +65,38 @@ func (s *stepCreateImage) Run(_ context.Context, state multistep.StateBag) multi * re-use step_list_images DONE * Documentation * Configuration (master/builder images & entry, destination stuff, etc) + * Image entry for both master/builder + https://github.com/hashicorp/packer/issues/6833 * split master/builder image/connection config. i.e. build anything, master only linux * correct artifact DONE + * Cleanup this step */ return multistep.ActionContinue } -func (s *stepCreateImage) Cleanup(state multistep.StateBag) {} +func (s *stepCreateImage) Cleanup(state multistep.StateBag) { + _, cancelled := state.GetOk(multistep.StateCancelled) + _, halted := state.GetOk(multistep.StateHalted) + if !cancelled && !halted { + return + } + + client := state.Get("client").(*compute.ComputeClient) + config := state.Get("config").(*Config) + + ui := state.Get("ui").(packer.Ui) + ui.Say("Cleaning up Image...") + + machineImageClient := client.MachineImages() + deleteMI := &compute.DeleteMachineImageInput{ + Name: config.ImageName, + } + + if err := machineImageClient.DeleteMachineImage(deleteMI); err != nil { + ui.Error(fmt.Sprintf("Error cleaning up machine image: %s", err)) + return + } + + ui.Message(fmt.Sprintf("Deleted Image: %s", config.ImageName)) +} diff --git a/builder/oracle/classic/step_upload_image.go b/builder/oracle/classic/step_upload_image.go new file mode 100644 index 000000000..74c93b969 --- /dev/null +++ b/builder/oracle/classic/step_upload_image.go @@ -0,0 +1,83 @@ +package classic + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" + "github.com/hashicorp/packer/template/interpolate" +) + +type stepUploadImage struct { + uploadImageCommand string +} + +type uploadCmdData struct { + Username string + Password string + AccountID string + ImageFile string + SegmentPath string +} + +func (s *stepUploadImage) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + comm := state.Get("communicator").(packer.Communicator) + config := state.Get("config").(*Config) + runID := state.Get("run_id").(string) + + imageFile := fmt.Sprintf("%s.tar.gz", config.ImageName) + state.Put("image_file", imageFile) + + config.ctx.Data = uploadCmdData{ + Username: config.Username, + Password: config.Password, + AccountID: config.IdentityDomain, + ImageFile: imageFile, + SegmentPath: fmt.Sprintf("compute_images_segments/%s/_segment_/%s", imageFile, runID), + } + uploadImageCmd, err := interpolate.Render(s.uploadImageCommand, &config.ctx) + if err != nil { + err := fmt.Errorf("Error processing image upload command: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + command := fmt.Sprintf(`#!/bin/sh + set -e + set -x + mkdir /builder + mkfs -t ext3 /dev/xvdb + mount /dev/xvdb /builder + chown opc:opc /builder + cd /builder + dd if=/dev/xvdc bs=8M status=progress | cp --sparse=always /dev/stdin diskimage.raw + tar czSf ./diskimage.tar.gz ./diskimage.raw + rm diskimage.raw + %s`, uploadImageCmd) + + dest := "/tmp/create-packer-diskimage.sh" + comm.Upload(dest, strings.NewReader(command), nil) + cmd := &packer.RemoteCmd{ + Command: fmt.Sprintf("sudo /bin/sh %s", dest), + } + if err := cmd.StartWithUi(comm, ui); err != nil { + err = fmt.Errorf("Problem creating image`: %s", err) + ui.Error(err.Error()) + state.Put("error", err) + return multistep.ActionHalt + } + + if cmd.ExitStatus != 0 { + err = fmt.Errorf("Create Disk Image command failed with exit code %d", cmd.ExitStatus) + ui.Error(err.Error()) + state.Put("error", err) + return multistep.ActionHalt + } + return multistep.ActionContinue +} + +func (s *stepUploadImage) Cleanup(state multistep.StateBag) {}