Move to using a diskset
Need to store lun numbers for data disks as well
This commit is contained in:
parent
3a3e6e525b
commit
12f746b2b5
|
@ -432,8 +432,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
artifact.Resources = append(artifact.Resources, b.config.SharedImageGalleryDestination.ResourceID(info.SubscriptionID))
|
||||
}
|
||||
if b.config.SkipCleanup {
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
if d, ok := state.GetOk(stateBagKey_Diskset); ok {
|
||||
for _, disk := range d.([]client.Resource) {
|
||||
artifact.Resources = append(artifact.Resources, disk.String())
|
||||
}
|
||||
}
|
||||
if d, ok := state.GetOk(stateBagKey_OSDiskSnapshotResourceID); ok {
|
||||
artifact.Resources = append(artifact.Resources, d.(string))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package chroot
|
||||
|
||||
const (
|
||||
stateBagKey_OSDiskResourceID = "os_disk_resource_id"
|
||||
stateBagKey_Diskset = "diskset"
|
||||
stateBagKey_OSDiskSnapshotResourceID = "os_disk_snapshot_resource_id"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package chroot
|
||||
|
||||
import "github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
// Diskset represents all of the disks or snapshots associated with an image.
|
||||
// It maps lun to resource ids. The OS disk is stored with lun=-1.
|
||||
type Diskset map[int]client.Resource
|
||||
|
||||
// OS return the OS disk resource ID or nil if it is not assigned
|
||||
func (ds Diskset) OS() *client.Resource {
|
||||
if r, ok := ds[-1]; ok {
|
||||
return &r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Data return the data disk resource ID or nil if it is not assigned
|
||||
func (ds Diskset) Data(lun int) *client.Resource {
|
||||
if r, ok := ds[lun]; ok {
|
||||
return &r
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package chroot
|
||||
|
||||
import "github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
// diskset easily creates a diskset for testing
|
||||
func diskset(ids ...string) Diskset {
|
||||
diskset := make(Diskset)
|
||||
for i, id := range ids {
|
||||
r, err := client.ParseResourceID(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
diskset[i-1] = r
|
||||
}
|
||||
return diskset
|
||||
}
|
|
@ -20,7 +20,8 @@ type StepAttachDisk struct {
|
|||
func (s *StepAttachDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().String()
|
||||
|
||||
ui.Say(fmt.Sprintf("Attaching disk '%s'", diskResourceID))
|
||||
|
||||
|
@ -67,7 +68,8 @@ func (s *StepAttachDisk) CleanupFunc(state multistep.StateBag) error {
|
|||
if s.attached {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().String()
|
||||
|
||||
ui.Say(fmt.Sprintf("Detaching disk '%s'", diskResourceID))
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ func TestStepAttachDisk_Run(t *testing.T) {
|
|||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{})
|
||||
state.Put("ui", ui)
|
||||
state.Put(stateBagKey_OSDiskResourceID, "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1")
|
||||
state.Put(stateBagKey_Diskset, diskset("/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"))
|
||||
|
||||
got := s.Run(context.TODO(), state)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
|
|
|
@ -28,7 +28,8 @@ type StepCreateImage struct {
|
|||
func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
diskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
diskResourceID := diskset.OS().String()
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating image %s\n using %s for os disk.",
|
||||
s.ImageResourceID,
|
||||
|
|
|
@ -7,12 +7,12 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
)
|
||||
|
||||
var _ multistep.Step = &StepCreateNewDiskset{}
|
||||
|
@ -22,7 +22,7 @@ type StepCreateNewDiskset struct {
|
|||
OSDiskSizeGB int32 // optional, ignored if 0
|
||||
OSDiskStorageAccountType string // from compute.DiskStorageAccountTypes
|
||||
|
||||
subscriptionID, resourceGroup, diskName string // split out resource id
|
||||
disks Diskset
|
||||
|
||||
HyperVGeneration string // For OS disk
|
||||
|
||||
|
@ -39,38 +39,56 @@ type StepCreateNewDiskset struct {
|
|||
SkipCleanup bool
|
||||
}
|
||||
|
||||
func parseDiskResourceID(resourceID string) (subscriptionID, resourceGroup, diskName string, err error) {
|
||||
r, err := azure.ParseResourceID(resourceID)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
if !strings.EqualFold(r.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(r.ResourceType, "disks") {
|
||||
return "", "", "", fmt.Errorf("Resource %q is not of type Microsoft.Compute/disks", resourceID)
|
||||
}
|
||||
|
||||
return r.SubscriptionID, r.ResourceGroup, r.ResourceName, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDiskset) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
state.Put(stateBagKey_OSDiskResourceID, s.OSDiskID)
|
||||
ui.Say(fmt.Sprintf("Creating disk '%s'", s.OSDiskID))
|
||||
s.disks = make(map[int]client.Resource)
|
||||
|
||||
var err error
|
||||
s.subscriptionID, s.resourceGroup, s.diskName, err = parseDiskResourceID(s.OSDiskID)
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error parsing resource id '%s': %v", s.OSDiskID, err)
|
||||
errorMessage := func(format string, params ...interface{}) multistep.StepAction {
|
||||
err := fmt.Errorf("StepCreateNewDisk.Run: error: "+format, params...)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// we always have an OS disk
|
||||
osDisk, err := client.ParseResourceID(s.OSDiskID)
|
||||
if err != nil {
|
||||
return errorMessage("error parsing resource id '%s': %v", s.OSDiskID, err)
|
||||
}
|
||||
if !strings.EqualFold(osDisk.Provider, "Microsoft.Compute") ||
|
||||
!strings.EqualFold(osDisk.ResourceType.String(), "disks") {
|
||||
return errorMessage("Resource %q is not of type Microsoft.Compute/disks", s.OSDiskID)
|
||||
}
|
||||
|
||||
// transform step config to disk model
|
||||
disk := s.getOSDiskDefinition(azcli)
|
||||
|
||||
// Initiate disk creation
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, osDisk.ResourceGroup, osDisk.ResourceName.String(), disk)
|
||||
if err != nil {
|
||||
return errorMessage("Failed to initiate resource creation: %q", osDisk)
|
||||
}
|
||||
s.disks[-1] = osDisk // save the resoure we just create in our disk set
|
||||
state.Put(stateBagKey_Diskset, s.disks) // update the statebag
|
||||
ui.Say(fmt.Sprintf("Creating disk %q", s.OSDiskID))
|
||||
|
||||
// Wait for completion
|
||||
{
|
||||
cli := azcli.PollClient() // quick polling for quick operations
|
||||
cli.PollingDelay = time.Second
|
||||
err = f.WaitForCompletionRef(ctx, cli)
|
||||
if err != nil {
|
||||
return errorMessage(
|
||||
"error creating new disk '%s': %v", s.OSDiskID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDiskset) getOSDiskDefinition(azcli client.AzureClientSet) compute.Disk {
|
||||
disk := compute.Disk{
|
||||
Location: to.StringPtr(s.Location),
|
||||
DiskProperties: &compute.DiskProperties{
|
||||
|
@ -99,7 +117,8 @@ func (s *StepCreateNewDiskset) Run(ctx context.Context, state multistep.StateBag
|
|||
disk.CreationData.ImageReference = &compute.ImageDiskReference{
|
||||
ID: to.StringPtr(fmt.Sprintf(
|
||||
"/subscriptions/%s/providers/Microsoft.Compute/locations/%s/publishers/%s/artifacttypes/vmimage/offers/%s/skus/%s/versions/%s",
|
||||
s.subscriptionID, s.Location, s.SourcePlatformImage.Publisher, s.SourcePlatformImage.Offer, s.SourcePlatformImage.Sku, s.SourcePlatformImage.Version)),
|
||||
azcli.SubscriptionID(), s.Location,
|
||||
s.SourcePlatformImage.Publisher, s.SourcePlatformImage.Offer, s.SourcePlatformImage.Sku, s.SourcePlatformImage.Version)),
|
||||
}
|
||||
case s.SourceOSDiskResourceID != "":
|
||||
disk.CreationData.CreateOption = compute.Copy
|
||||
|
@ -112,23 +131,7 @@ func (s *StepCreateNewDiskset) Run(ctx context.Context, state multistep.StateBag
|
|||
default:
|
||||
disk.CreationData.CreateOption = compute.Empty
|
||||
}
|
||||
|
||||
f, err := azcli.DisksClient().CreateOrUpdate(ctx, s.resourceGroup, s.diskName, disk)
|
||||
if err == nil {
|
||||
cli := azcli.PollClient() // quick polling for quick operations
|
||||
cli.PollingDelay = time.Second
|
||||
err = f.WaitForCompletionRef(ctx, cli)
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Run: error: %+v", err)
|
||||
err := fmt.Errorf(
|
||||
"error creating new disk '%s': %v", s.OSDiskID, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
return disk
|
||||
}
|
||||
|
||||
func (s *StepCreateNewDiskset) Cleanup(state multistep.StateBag) {
|
||||
|
@ -136,21 +139,24 @@ func (s *StepCreateNewDiskset) Cleanup(state multistep.StateBag) {
|
|||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say(fmt.Sprintf("Waiting for disk %q detach to complete", s.OSDiskID))
|
||||
err := NewDiskAttacher(azcli).WaitForDetach(context.Background(), s.OSDiskID)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("error detaching disk %q: %s", s.OSDiskID, err))
|
||||
}
|
||||
for _, d := range s.disks {
|
||||
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", s.OSDiskID))
|
||||
ui.Say(fmt.Sprintf("Waiting for disk %q detach to complete", d))
|
||||
err := NewDiskAttacher(azcli).WaitForDetach(context.Background(), d.String())
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("error detaching disk %q: %s", d, err))
|
||||
}
|
||||
|
||||
f, err := azcli.DisksClient().Delete(context.TODO(), s.resourceGroup, s.diskName)
|
||||
if err == nil {
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting disk '%s': %v.", s.OSDiskID, err))
|
||||
ui.Say(fmt.Sprintf("Deleting disk %q", d))
|
||||
|
||||
f, err := azcli.DisksClient().Delete(context.TODO(), d.ResourceGroup, d.ResourceName.String())
|
||||
if err == nil {
|
||||
err = f.WaitForCompletionRef(context.TODO(), azcli.PollClient())
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("StepCreateNewDisk.Cleanup: error: %+v", err)
|
||||
ui.Error(fmt.Sprintf("error deleting disk '%s': %v.", d, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,8 @@ func TestStepCreateNewDisk_Run(t *testing.T) {
|
|||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("azureclient", &client.AzureClientSetMock{
|
||||
DisksClientMock: m,
|
||||
SubscriptionIDMock: "SubscriptionID",
|
||||
DisksClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ func parseSnapshotResourceID(resourceID string) (subscriptionID, resourceGroup,
|
|||
func (s *StepCreateSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
azcli := state.Get("azureclient").(client.AzureClientSet)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
osDiskResourceID := state.Get(stateBagKey_OSDiskResourceID).(string)
|
||||
diskset := state.Get(stateBagKey_Diskset).(Diskset)
|
||||
osDiskResourceID := diskset.OS().String()
|
||||
|
||||
state.Put(stateBagKey_OSDiskSnapshotResourceID, s.ResourceID)
|
||||
ui.Say(fmt.Sprintf("Creating snapshot '%s'", s.ResourceID))
|
||||
|
|
|
@ -94,7 +94,7 @@ func TestStepCreateSnapshot_Run(t *testing.T) {
|
|||
"properties": {
|
||||
"creationData": {
|
||||
"createOption": "Copy",
|
||||
"sourceResourceId": "osdiskresourceid"
|
||||
"sourceResourceId": "/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"
|
||||
},
|
||||
"incremental": false
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ func TestStepCreateSnapshot_Run(t *testing.T) {
|
|||
SnapshotsClientMock: m,
|
||||
})
|
||||
state.Put("ui", packer.TestUi(t))
|
||||
state.Put(stateBagKey_OSDiskResourceID, "osdiskresourceid")
|
||||
state.Put(stateBagKey_Diskset, diskset("/subscriptions/12345/resourceGroups/group1/providers/Microsoft.Compute/disks/disk1"))
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := &StepCreateSnapshot{
|
||||
|
|
Loading…
Reference in New Issue