packer-cn/builder/linode/step_create_linode.go

98 lines
2.6 KiB
Go

package linode
import (
"context"
"errors"
"time"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/linode/linodego"
)
type stepCreateLinode struct {
client linodego.Client
}
func (s *stepCreateLinode) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
c := state.Get("config").(*Config)
ui := state.Get("ui").(packersdk.Ui)
ui.Say("Creating Linode...")
createOpts := linodego.InstanceCreateOptions{
RootPass: c.Comm.Password(),
AuthorizedKeys: []string{string(c.Comm.SSHPublicKey)},
Region: c.Region,
Type: c.InstanceType,
Label: c.Label,
Image: c.Image,
SwapSize: &c.SwapSize,
}
instance, err := s.client.CreateInstance(ctx, createOpts)
if err != nil {
err = errors.New("Error creating Linode: " + err.Error())
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("instance", instance)
// wait until instance is running
for instance.Status != linodego.InstanceRunning {
time.Sleep(2 * time.Second)
if instance, err = s.client.GetInstance(ctx, instance.ID); err != nil {
err = errors.New("Error creating Linode: " + err.Error())
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("instance", instance)
// instance_id is the generic term used so that users can have access to the
// instance id inside of the provisioners, used in step_provision.
state.Put("instance_id", instance.ID)
}
disk, err := s.findDisk(ctx, instance.ID)
if err != nil {
err = errors.New("Error creating Linode: " + err.Error())
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
} else if disk == nil {
err := errors.New("Error creating Linode: no suitable disk was found")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
state.Put("disk", disk)
return multistep.ActionContinue
}
func (s *stepCreateLinode) findDisk(ctx context.Context, instanceID int) (*linodego.InstanceDisk, error) {
disks, err := s.client.ListInstanceDisks(ctx, instanceID, nil)
if err != nil {
return nil, err
}
for _, disk := range disks {
if disk.Filesystem != linodego.FilesystemSwap {
return &disk, nil
}
}
return nil, nil
}
func (s *stepCreateLinode) Cleanup(state multistep.StateBag) {
instance, ok := state.GetOk("instance")
if !ok {
return
}
ui := state.Get("ui").(packersdk.Ui)
if err := s.client.DeleteInstance(context.Background(), instance.(*linodego.Instance).ID); err != nil {
ui.Error("Error cleaning up Linode: " + err.Error())
}
}