Merge pull request #7211 from riezebosch/master

arm-builder: specify zone resilient image from config
This commit is contained in:
Paul Meyer 2019-03-19 08:59:29 -07:00 committed by GitHub
commit e4bea87a20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 0 deletions

View File

@ -151,6 +151,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
b.config.Location = *group.Location b.config.Location = *group.Location
} }
b.config.validateLocationZoneResiliency(ui.Say)
if b.config.StorageAccount != "" { if b.config.StorageAccount != "" {
account, err := b.getBlobAccount(ctx, azureClient, b.config.ResourceGroupName, b.config.StorageAccount) account, err := b.getBlobAccount(ctx, azureClient, b.config.ResourceGroupName, b.config.StorageAccount)
if err != nil { if err != nil {

View File

@ -107,6 +107,7 @@ type Config struct {
ManagedImageOSDiskSnapshotName string `mapstructure:"managed_image_os_disk_snapshot_name"` ManagedImageOSDiskSnapshotName string `mapstructure:"managed_image_os_disk_snapshot_name"`
ManagedImageDataDiskSnapshotPrefix string `mapstructure:"managed_image_data_disk_snapshot_prefix"` ManagedImageDataDiskSnapshotPrefix string `mapstructure:"managed_image_data_disk_snapshot_prefix"`
manageImageLocation string manageImageLocation string
ManagedImageZoneResilient bool `mapstructure:"managed_image_zone_resilient"`
// Deployment // Deployment
AzureTags map[string]*string `mapstructure:"azure_tags"` AzureTags map[string]*string `mapstructure:"azure_tags"`
@ -196,6 +197,9 @@ func (c *Config) toImageParameters() *compute.Image {
SourceVirtualMachine: &compute.SubResource{ SourceVirtualMachine: &compute.SubResource{
ID: to.StringPtr(c.toVMID()), ID: to.StringPtr(c.toVMID()),
}, },
StorageProfile: &compute.ImageStorageProfile{
ZoneResilient: to.BoolPtr(c.ManagedImageZoneResilient),
},
}, },
Location: to.StringPtr(c.Location), Location: to.StringPtr(c.Location),
Tags: c.AzureTags, Tags: c.AzureTags,
@ -721,3 +725,23 @@ func isValidAzureName(re *regexp.Regexp, rgn string) bool {
!strings.HasSuffix(rgn, ".") && !strings.HasSuffix(rgn, ".") &&
!strings.HasSuffix(rgn, "-") !strings.HasSuffix(rgn, "-")
} }
func (c *Config) validateLocationZoneResiliency(say func(s string)) {
// Docs on regions that support Availibility Zones:
// https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#regions-that-support-availability-zones
// Query technical names for locations:
// az account list-locations --query '[].name' -o tsv
var zones = make(map[string]struct{})
zones["westeurope"] = struct{}{}
zones["centralus"] = struct{}{}
zones["eastus2"] = struct{}{}
zones["francecentral"] = struct{}{}
zones["northeurope"] = struct{}{}
zones["southeastasia"] = struct{}{}
zones["westus2"] = struct{}{}
if _, ok := zones[c.Location]; !ok {
say(fmt.Sprintf("WARNING: Zone resiliency may not be supported in %s, checkout the docs at https://docs.microsoft.com/en-us/azure/availability-zones/", c.Location))
}
}

View File

@ -794,6 +794,51 @@ func TestConfigShouldRejectExcessiveTagValueLength(t *testing.T) {
} }
} }
func TestConfigZoneResilientShouldDefaultToFalse(t *testing.T) {
config := map[string]interface{}{
"managed_image_name": "ignore",
"managed_image_resource_group_name": "ignore",
"build_resource_group_name": "ignore",
"image_publisher": "igore",
"image_offer": "ignore",
"image_sku": "ignore",
"os_type": "linux",
}
c, _, err := newConfig(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
p := c.toImageParameters()
if *p.ImageProperties.StorageProfile.ZoneResilient {
t.Fatal("expected zone resilient default to be false")
}
}
func TestConfigZoneResilientSetFromConfig(t *testing.T) {
config := map[string]interface{}{
"managed_image_name": "ignore",
"managed_image_resource_group_name": "ignore",
"build_resource_group_name": "ignore",
"image_publisher": "igore",
"image_offer": "ignore",
"image_sku": "ignore",
"os_type": "linux",
"managed_image_zone_resilient": true,
}
c, _, err := newConfig(config, getPackerConfiguration())
if err != nil {
t.Fatal(err)
}
p := c.toImageParameters()
if *p.ImageProperties.StorageProfile.ZoneResilient == false {
t.Fatal("expected managed image zone resilient to be true from config")
}
}
func TestConfigShouldRejectMissingCustomDataFile(t *testing.T) { func TestConfigShouldRejectMissingCustomDataFile(t *testing.T) {
config := map[string]interface{}{ config := map[string]interface{}{
"capture_name_prefix": "ignore", "capture_name_prefix": "ignore",
@ -1636,7 +1681,42 @@ func TestConfigShouldRejectSharedImageGalleryWithVhdTarget(t *testing.T) {
if err != nil { if err != nil {
t.Log("expected an error if Shared Image Gallery source is used with VHD target", err) t.Log("expected an error if Shared Image Gallery source is used with VHD target", err)
} }
}
func Test_GivenZoneNotSupportingResiliency_ConfigValidate_ShouldWarn(t *testing.T) {
builderValues := getArmBuilderConfiguration()
builderValues["managed_image_zone_resilient"] = "true"
builderValues["location"] = "ukwest"
c, _, err := newConfig(builderValues, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
var m = ""
c.validateLocationZoneResiliency(func(s string) { m = s })
if m != "WARNING: Zone resiliency may not be supported in ukwest, checkout the docs at https://docs.microsoft.com/en-us/azure/availability-zones/" {
t.Errorf("warning message not as expected: %s", m)
}
}
func Test_GivenZoneSupportingResiliency_ConfigValidate_ShouldNotWarn(t *testing.T) {
builderValues := getArmBuilderConfiguration()
builderValues["managed_image_zone_resilient"] = "true"
builderValues["location"] = "westeurope"
c, _, err := newConfig(builderValues, getPackerConfiguration())
if err != nil {
t.Errorf("newConfig failed with %q", err)
}
var m = ""
c.validateLocationZoneResiliency(func(s string) { m = s })
if m != "" {
t.Errorf("warning message not as expected: %s", m)
}
} }
func getArmBuilderConfiguration() map[string]string { func getArmBuilderConfiguration() map[string]string {

View File

@ -334,6 +334,9 @@ Providing `temp_resource_group_name` or `location` in combination with
disk(s) is created with the same prefix as this value before the VM is disk(s) is created with the same prefix as this value before the VM is
captured. captured.
- `managed_image_zone_resilient` (bool) Store the image in zone-resilient storage. You need to create it
in a region that supports [availability zones](https://docs.microsoft.com/en-us/azure/availability-zones/az-overview).
## Basic Example ## Basic Example
Here is a basic example for Azure. Here is a basic example for Azure.