diff --git a/builder/oracle/classic/builder.go b/builder/oracle/classic/builder.go index 8537289cf..088ff4dbc 100644 --- a/builder/oracle/classic/builder.go +++ b/builder/oracle/classic/builder.go @@ -80,6 +80,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &common.StepProvision{}, &stepSnapshot{}, + &stepListImages{}, } // Run the steps diff --git a/builder/oracle/classic/config.go b/builder/oracle/classic/config.go index 7b2f7dfb2..e0c82beb2 100644 --- a/builder/oracle/classic/config.go +++ b/builder/oracle/classic/config.go @@ -23,9 +23,13 @@ type Config struct { apiEndpointURL *url.URL // Image - ImageName string `mapstructure:"image_name"` - Shape string `mapstructure:"shape"` - ImageList string `mapstructure:"image_list"` + ImageName string `mapstructure:"image_name"` + Shape string `mapstructure:"shape"` + SourceImageList string `mapstructure:"source_image_list"` + DestImageList string `mapstructure:"dest_image_list"` + // Optional; if you don't enter anything, the image list description + // will read "Packer-built image list" + DestImageListDescription string `mapstructure:"dest_image_list_description` // Optional. Describes what computers are allowed to reach your instance // via SSH. This whitelist must contain the computer you're running Packer // from. It defaults to public-internet, meaning that you can SSH into your @@ -63,12 +67,12 @@ func NewConfig(raws ...interface{}) (*Config, error) { // Validate that all required fields are present var errs *packer.MultiError required := map[string]string{ - "username": c.Username, - "password": c.Password, - "api_endpoint": c.APIEndpoint, - "identity_domain": c.IdentityDomain, - "image_list": c.ImageList, - "shape": c.Shape, + "username": c.Username, + "password": c.Password, + "api_endpoint": c.APIEndpoint, + "identity_domain": c.IdentityDomain, + "source_image_list": c.SourceImageList, + "shape": c.Shape, } for k, v := range required { if v == "" { diff --git a/builder/oracle/classic/step_create_instance.go b/builder/oracle/classic/step_create_instance.go index ea840cb22..891fda33e 100644 --- a/builder/oracle/classic/step_create_instance.go +++ b/builder/oracle/classic/step_create_instance.go @@ -35,7 +35,7 @@ func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu input := &compute.CreateInstanceInput{ Name: config.ImageName, Shape: config.Shape, - ImageList: config.ImageList, + ImageList: config.SourceImageList, SSHKeys: []string{keyName}, Networking: map[string]compute.NetworkingInfo{"eth0": netInfo}, } diff --git a/builder/oracle/classic/step_list_images.go b/builder/oracle/classic/step_list_images.go new file mode 100644 index 000000000..8d0c5ee12 --- /dev/null +++ b/builder/oracle/classic/step_list_images.go @@ -0,0 +1,70 @@ +package classic + +import ( + "context" + "fmt" + + "github.com/hashicorp/go-oracle-terraform/compute" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +type stepListImages struct{} + +func (s *stepListImages) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + // get variables from state + ui := state.Get("ui").(packer.Ui) + config := state.Get("config").(*Config) + client := state.Get("client").(*compute.ComputeClient) + ui.Say("Adding image to image list...") + + // TODO: Try to get image list + imageListClient := client.ImageList() + getInput := compute.GetImageListInput{ + Name: config.DestImageList, + } + imList, err := imageListClient.GetImageList(&getInput) + if err != nil { + ui.Say(fmt.Sprintf(err.Error())) + // If the list didn't exist, create it. + ui.Say(fmt.Sprintf("Creating image list: %s", config.DestImageList)) + + ilInput := compute.CreateImageListInput{ + Name: config.DestImageList, + Description: "Packer-built image list", + } + + // Load the packer-generated SSH key into the Oracle Compute cloud. + imList, err = imageListClient.CreateImageList(&ilInput) + if err != nil { + err = fmt.Errorf("Problem creating an image list through Oracle's API: %s", err) + ui.Error(err.Error()) + state.Put("error", err) + return multistep.ActionHalt + } + ui.Message(fmt.Sprintf("Image list %s created!", imList.URI)) + } + + // Now create and image list entry for the image into that list. + snap := state.Get("snapshot").(*compute.Snapshot) + entriesClient := client.ImageListEntries() + entriesInput := compute.CreateImageListEntryInput{ + Name: config.DestImageList, + MachineImages: []string{fmt.Sprintf("Compute-%s/%s/%s", config.IdentityDomain, config.Username, snap.MachineImage)}, + Version: 1, + } + entryInfo, err := entriesClient.CreateImageListEntry(&entriesInput) + if err != nil { + err = fmt.Errorf("Problem creating an image list entry: %s", err) + ui.Error(err.Error()) + state.Put("error", err) + return multistep.ActionHalt + } + ui.Message(fmt.Sprintf("created image list entry %s", entryInfo.Name)) + return multistep.ActionContinue +} + +func (s *stepListImages) Cleanup(state multistep.StateBag) { + // Nothing to do + return +} diff --git a/builder/oracle/classic/step_snapshot.go b/builder/oracle/classic/step_snapshot.go index 602ebd1ad..b98530691 100644 --- a/builder/oracle/classic/step_snapshot.go +++ b/builder/oracle/classic/step_snapshot.go @@ -42,5 +42,22 @@ func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multiste } func (s *stepSnapshot) Cleanup(state multistep.StateBag) { - // Nothing to do + // Delete the snapshot + ui := state.Get("ui").(packer.Ui) + ui.Say("Creating Snapshot...") + client := state.Get("client").(*compute.ComputeClient) + snap := state.Get("snapshot").(*compute.Snapshot) + snapClient := client.Snapshots() + snapInput := compute.DeleteSnapshotInput{ + Snapshot: snap.Name, + MachineImage: snap.MachineImage, + } + machineClient := client.MachineImages() + err := snapClient.DeleteSnapshot(machineClient, &snapInput) + if err != nil { + err = fmt.Errorf("Problem deleting snapshot: %s", err) + ui.Error(err.Error()) + state.Put("error", err) + } + return }