Skip to content
This repository was archived by the owner on May 22, 2020. It is now read-only.

Commit 9472e03

Browse files
authored
Merge pull request #449 from justinsb/copy-snapshots-in-parallel
Copy snapshots in parallel
2 parents 4762a98 + 57cb00f commit 9472e03

File tree

1 file changed

+59
-27
lines changed
  • imagebuilder/pkg/imagebuilder

1 file changed

+59
-27
lines changed

imagebuilder/pkg/imagebuilder/aws.go

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ limitations under the License.
2121
package imagebuilder
2222

2323
import (
24-
"fmt"
25-
"time"
26-
2724
"crypto/md5"
2825
"encoding/hex"
26+
"fmt"
27+
"sync"
28+
"time"
2929

3030
"github.com/aws/aws-sdk-go/aws"
3131
"github.com/aws/aws-sdk-go/aws/awserr"
@@ -565,7 +565,8 @@ type AWSImage struct {
565565
region string
566566
imageID string
567567

568-
cachedImage *ec2.Image
568+
cachedImageMutex sync.Mutex
569+
cachedImage *ec2.Image
569570
}
570571

571572
// ID returns the AWS identifier for the image
@@ -670,6 +671,9 @@ func waitSnapshotCompleted(client *ec2.EC2, snapshotID string) error {
670671
}
671672

672673
func (i *AWSImage) image() (*ec2.Image, error) {
674+
i.cachedImageMutex.Lock()
675+
defer i.cachedImageMutex.Unlock()
676+
673677
if i.cachedImage != nil {
674678
return i.cachedImage, nil
675679
}
@@ -781,7 +785,7 @@ func (i *AWSImage) ensurePublic() error {
781785

782786
// ReplicateImage copies the image to all accessable AWS regions
783787
func (i *AWSImage) ReplicateImage(makePublic bool) (map[string]Image, error) {
784-
imagesByRegion := make(map[string]Image)
788+
var results sync.Map
785789

786790
glog.V(2).Infof("AWS DescribeRegions")
787791
request := &ec2.DescribeRegionsInput{}
@@ -790,35 +794,63 @@ func (i *AWSImage) ReplicateImage(makePublic bool) (map[string]Image, error) {
790794
return nil, fmt.Errorf("error listing ec2 regions: %v", err)
791795

792796
}
793-
imagesByRegion[i.region] = i
797+
results.Store(i.region, i)
798+
799+
var wg sync.WaitGroup
794800

795801
for _, region := range response.Regions {
796-
regionName := aws.StringValue(region.RegionName)
797-
if imagesByRegion[regionName] != nil {
798-
continue
799-
}
802+
go func(regionName string) {
803+
var image *AWSImage
804+
if v, ok := results.Load(regionName); ok {
805+
image = v.(*AWSImage)
806+
}
800807

801-
imageID, err := i.copyImageToRegion(regionName)
802-
if err != nil {
803-
return nil, fmt.Errorf("error copying image to region %q: %v", regionName, err)
804-
}
805-
targetEC2 := ec2.New(session.New(), &aws.Config{Region: &regionName})
806-
imagesByRegion[regionName] = &AWSImage{
807-
ec2: targetEC2,
808-
region: regionName,
809-
imageID: imageID,
810-
}
811-
}
808+
if image == nil {
809+
imageID, err := i.copyImageToRegion(regionName)
810+
if err != nil {
811+
results.Store(regionName, fmt.Errorf("error copying image to region %q: %v", regionName, err))
812+
wg.Done()
813+
return
814+
}
815+
targetEC2 := ec2.New(session.New(), &aws.Config{Region: &regionName})
816+
image = &AWSImage{
817+
ec2: targetEC2,
818+
region: regionName,
819+
imageID: imageID,
820+
}
812821

813-
if makePublic {
814-
for regionName, image := range imagesByRegion {
815-
err := image.EnsurePublic()
816-
if err != nil {
817-
return nil, fmt.Errorf("error making image public in region %q: %v", regionName, err)
822+
results.Store(regionName, image)
818823
}
819-
}
824+
825+
if makePublic {
826+
err := image.EnsurePublic()
827+
if err != nil {
828+
results.Store(regionName, fmt.Errorf("error making image public in region %q: %v", regionName, err))
829+
wg.Done()
830+
return
831+
}
832+
}
833+
834+
wg.Done()
835+
}(aws.StringValue(region.RegionName))
836+
wg.Add(1)
820837
}
821838

839+
wg.Wait()
840+
841+
imagesByRegion := make(map[string]Image)
842+
var returnError error
843+
results.Range(func(k, v interface{}) bool {
844+
if err, ok := v.(error); ok {
845+
returnError = err
846+
return false
847+
}
848+
imagesByRegion[k.(string)] = v.(*AWSImage)
849+
return true
850+
})
851+
if returnError != nil {
852+
return nil, returnError
853+
}
822854
return imagesByRegion, nil
823855
}
824856

0 commit comments

Comments
 (0)