Skip to content

Commit

Permalink
builder: initiate image transfers in parallel.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewsomething committed Feb 12, 2024
1 parent 601c064 commit 477c366
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
2 changes: 1 addition & 1 deletion builder/digitalocean/builder_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const (
"ssh_username": "root",
"user_data": "",
"user_data_file": "",
"snapshot_regions": ["nyc2", "nyc3"]
"snapshot_regions": ["nyc1", "nyc2", "nyc3"]
}]
}
`
Expand Down
84 changes: 47 additions & 37 deletions builder/digitalocean/step_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/digitalocean/godo"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"golang.org/x/sync/errgroup"
)

type stepSnapshot struct {
Expand Down Expand Up @@ -65,61 +66,70 @@ func (s *stepSnapshot) Run(ctx context.Context, state multistep.StateBag) multis
return multistep.ActionHalt
}

var imageId int
if len(images) == 1 {
imageId = images[0].ID
log.Printf("Snapshot image ID: %d", imageId)
} else {
err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}

if len(c.SnapshotRegions) > 0 {
regionSet := make(map[string]struct{})
regionSet := make(map[string]bool)
regions := make([]string, 0, len(c.SnapshotRegions))
regionSet[c.Region] = struct{}{}
regionSet[c.Region] = true
for _, region := range c.SnapshotRegions {
// If we already saw the region, then don't look again
if _, ok := regionSet[region]; ok {
if regionSet[region] {
continue
}

// Mark that we saw the region
regionSet[region] = struct{}{}
regionSet[region] = true

regions = append(regions, region)
}
snapshotRegions = regions

for transfer := range snapshotRegions {
transferRequest := &godo.ActionRequest{
"type": "transfer",
"region": snapshotRegions[transfer],
}

ui.Say(fmt.Sprintf("Transferring snapshot (ID: %d) to %s", images[0].ID, snapshotRegions[transfer]))
imageTransfer, _, err := client.ImageActions.Transfer(context.TODO(), images[0].ID, transferRequest)
if err != nil {
err := fmt.Errorf("Error transferring snapshot: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
eg, gCtx := errgroup.WithContext(ctx)
for _, r := range regions {
region := r
eg.Go(func() error {
transferRequest := &godo.ActionRequest{
"type": "transfer",
"region": region,
}

ui.Say(fmt.Sprintf("Transferring snapshot (ID: %d) to %s...", imageId, region))
imageTransfer, _, err := client.ImageActions.Transfer(gCtx, imageId, transferRequest)
if err != nil {
return fmt.Errorf("Error transferring snapshot: %s", err)
}

if err := WaitForImageState(
godo.ActionCompleted,
imageId,
imageTransfer.ID,
client, 20*time.Minute); err != nil {
return fmt.Errorf("Error waiting for snapshot transfer: %s", err)
}
ui.Say(fmt.Sprintf("Transfer to %s is complete.", region))

return nil
})
}

if err := WaitForImageState(godo.ActionCompleted, images[0].ID, imageTransfer.ID,
client, 20*time.Minute); err != nil {
// If we get an error the first time, actually report it
err := fmt.Errorf("Error waiting for snapshot transfer: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if err := eg.Wait(); err != nil {
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}

var imageId int
if len(images) == 1 {
imageId = images[0].ID
} else {
err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
snapshotRegions = append(snapshotRegions, c.Region)

log.Printf("Snapshot image ID: %d", imageId)
state.Put("snapshot_image_id", imageId)
state.Put("snapshot_name", c.SnapshotName)
state.Put("regions", snapshotRegions)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/zclconf/go-cty v1.13.3
golang.org/x/oauth2 v0.1.0
golang.org/x/sync v0.4.0
)

require (
Expand Down

0 comments on commit 477c366

Please sign in to comment.