diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index 7b67f4862..a18434914 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -449,6 +449,7 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) { stateBag.Put(constants.ArmManagedImageSharedGalleryName, b.config.SharedGalleryDestination.SigDestinationGalleryName) stateBag.Put(constants.ArmManagedImageSharedGalleryImageName, b.config.SharedGalleryDestination.SigDestinationImageName) stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersion, b.config.SharedGalleryDestination.SigDestinationImageVersion) + stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionStorageAccountType, b.config.SharedGalleryDestination.SigDestinationStorageAccountType) stateBag.Put(constants.ArmManagedImageSubscription, b.config.ClientConfig.SubscriptionID) stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate, b.config.SharedGalleryImageVersionEndOfLifeDate) stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionReplicaCount, b.config.SharedGalleryImageVersionReplicaCount) diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go index 7d9a2ac4a..6f35a2035 100644 --- a/builder/azure/arm/config.go +++ b/builder/azure/arm/config.go @@ -95,6 +95,9 @@ type SharedImageGalleryDestination struct { SigDestinationImageName string `mapstructure:"image_name"` SigDestinationImageVersion string `mapstructure:"image_version"` SigDestinationReplicationRegions []string `mapstructure:"replication_regions"` + // Specify a storage account type for the Shared Image Gallery Image Version. + // Defaults to `Standard_LRS`. Accepted values are `Standard_LRS` and `Standard_ZRS` + SigDestinationStorageAccountType string `mapstructure:"storage_account_type"` } type Config struct { @@ -158,7 +161,8 @@ type Config struct { // "gallery_name": "GalleryName", // "image_name": "ImageName", // "image_version": "1.0.0", - // "replication_regions": ["regionA", "regionB", "regionC"] + // "replication_regions": ["regionA", "regionB", "regionC"], + // "storage_account_type": "Standard_LRS" // } // "managed_image_name": "TargetImageName", // "managed_image_resource_group_name": "TargetResourceGroup" @@ -172,6 +176,7 @@ type Config struct { // image_name = "ImageName" // image_version = "1.0.0" // replication_regions = ["regionA", "regionB", "regionC"] + // storage_account_type = "Standard_LRS" // } // managed_image_name = "TargetImageName" // managed_image_resource_group_name = "TargetResourceGroup" @@ -1111,6 +1116,8 @@ func assertRequiredParametersSet(c *Config, errs *packersdk.MultiError) { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The os_type %q is invalid", c.OSType)) } + ///////////////////////////////////////////// + // Storage switch c.ManagedImageStorageAccountType { case "", string(compute.StorageAccountTypesStandardLRS): c.managedImageStorageAccountType = compute.StorageAccountTypesStandardLRS @@ -1120,6 +1127,10 @@ func assertRequiredParametersSet(c *Config, errs *packersdk.MultiError) { errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The managed_image_storage_account_type %q is invalid", c.ManagedImageStorageAccountType)) } + if ok, err := assertSigAllowedStorageAccountType(c.SharedGalleryDestination.SigDestinationStorageAccountType); !ok { + errs = packersdk.MultiErrorAppend(errs, err) + } + switch c.DiskCachingType { case string(compute.CachingTypesNone): c.diskCachingType = compute.CachingTypesNone @@ -1171,6 +1182,14 @@ func assertAllowedInboundIpAddresses(ipAddresses []string, setting string) (bool return true, nil } +func assertSigAllowedStorageAccountType(s string) (bool, error) { + _, err := getSigDestinationStorageAccountType(s) + if err != nil { + return false, err + } + return true, nil +} + func assertResourceGroupName(rgn, setting string) (bool, error) { if !isValidAzureName(reResourceGroupName, rgn) { return false, fmt.Errorf("The setting %s must match the regular expression %q, and not end with a '-' or '.'.", setting, validResourceGroupNameRe) diff --git a/builder/azure/arm/config.hcl2spec.go b/builder/azure/arm/config.hcl2spec.go index 73ddb834a..e520d2b9f 100644 --- a/builder/azure/arm/config.hcl2spec.go +++ b/builder/azure/arm/config.hcl2spec.go @@ -334,6 +334,7 @@ type FlatSharedImageGalleryDestination struct { SigDestinationImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"` SigDestinationImageVersion *string `mapstructure:"image_version" cty:"image_version" hcl:"image_version"` SigDestinationReplicationRegions []string `mapstructure:"replication_regions" cty:"replication_regions" hcl:"replication_regions"` + SigDestinationStorageAccountType *string `mapstructure:"storage_account_type" cty:"storage_account_type" hcl:"storage_account_type"` } // FlatMapstructure returns a new FlatSharedImageGalleryDestination. @@ -348,12 +349,13 @@ func (*SharedImageGalleryDestination) FlatMapstructure() interface{ HCL2Spec() m // The decoded values from this spec will then be applied to a FlatSharedImageGalleryDestination. func (*FlatSharedImageGalleryDestination) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "subscription": &hcldec.AttrSpec{Name: "subscription", Type: cty.String, Required: false}, - "resource_group": &hcldec.AttrSpec{Name: "resource_group", Type: cty.String, Required: false}, - "gallery_name": &hcldec.AttrSpec{Name: "gallery_name", Type: cty.String, Required: false}, - "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, - "image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false}, - "replication_regions": &hcldec.AttrSpec{Name: "replication_regions", Type: cty.List(cty.String), Required: false}, + "subscription": &hcldec.AttrSpec{Name: "subscription", Type: cty.String, Required: false}, + "resource_group": &hcldec.AttrSpec{Name: "resource_group", Type: cty.String, Required: false}, + "gallery_name": &hcldec.AttrSpec{Name: "gallery_name", Type: cty.String, Required: false}, + "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, + "image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false}, + "replication_regions": &hcldec.AttrSpec{Name: "replication_regions", Type: cty.List(cty.String), Required: false}, + "storage_account_type": &hcldec.AttrSpec{Name: "storage_account_type", Type: cty.String, Required: false}, } return s } diff --git a/builder/azure/arm/config_test.go b/builder/azure/arm/config_test.go index 98995d89a..83b51f937 100644 --- a/builder/azure/arm/config_test.go +++ b/builder/azure/arm/config_test.go @@ -1955,6 +1955,29 @@ func TestConfigShouldAllowSharedImageGalleryOptions(t *testing.T) { } +func TestConfigShouldRejectSharedImageGalleryInvalidStorageAccountType(t *testing.T) { + config := map[string]interface{}{ + "location": "ignore", + "subscription_id": "ignore", + "os_type": "linux", + "shared_image_gallery": map[string]string{ + "subscription": "ignore", + "resource_group": "ignore", + "gallery_name": "ignore", + "image_name": "ignore", + "image_version": "ignore", + "storage_account_type": "--invalid--", + }, + } + + var c Config + _, err := c.Prepare(config, getPackerConfiguration()) + if err != nil { + t.Log("config Shared Image Gallery with unsupported storage account type failed which is expected", err) + } + +} + func TestConfigShouldRejectSharedImageGalleryWithVhdTarget(t *testing.T) { config := map[string]interface{}{ "location": "ignore", diff --git a/builder/azure/arm/step_publish_to_shared_image_gallery.go b/builder/azure/arm/step_publish_to_shared_image_gallery.go index 86727dc83..629858e4c 100644 --- a/builder/azure/arm/step_publish_to_shared_image_gallery.go +++ b/builder/azure/arm/step_publish_to_shared_image_gallery.go @@ -37,6 +37,17 @@ func NewStepPublishToSharedImageGallery(client *AzureClient, ui packersdk.Ui, co return step } +func getSigDestinationStorageAccountType(s string) (compute.StorageAccountType, error) { + switch s { + case "", string(compute.StorageAccountTypeStandardLRS): + return compute.StorageAccountTypeStandardLRS, nil + case string(compute.StorageAccountTypeStandardZRS): + return compute.StorageAccountTypeStandardZRS, nil + default: + return "", fmt.Errorf("not an accepted value for shared_image_gallery_destination.storage_account_type") + } +} + func getSigDestination(state multistep.StateBag) SharedImageGalleryDestination { subscription := state.Get(constants.ArmManagedImageSubscription).(string) resourceGroup := state.Get(constants.ArmManagedImageSigPublishResourceGroup).(string) @@ -44,6 +55,7 @@ func getSigDestination(state multistep.StateBag) SharedImageGalleryDestination { imageName := state.Get(constants.ArmManagedImageSharedGalleryImageName).(string) imageVersion := state.Get(constants.ArmManagedImageSharedGalleryImageVersion).(string) replicationRegions := state.Get(constants.ArmManagedImageSharedGalleryReplicationRegions).([]string) + storageAccountType := state.Get(constants.ArmManagedImageSharedGalleryImageVersionStorageAccountType).(string) return SharedImageGalleryDestination{ SigDestinationSubscription: subscription, @@ -52,6 +64,7 @@ func getSigDestination(state multistep.StateBag) SharedImageGalleryDestination { SigDestinationImageName: imageName, SigDestinationImageVersion: imageVersion, SigDestinationReplicationRegions: replicationRegions, + SigDestinationStorageAccountType: storageAccountType, } } @@ -73,6 +86,13 @@ func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiI } else { endOfLifeDate = (*date.Time)(nil) } + + storageAccountType, err := getSigDestinationStorageAccountType(string(sharedImageGallery.SigDestinationStorageAccountType)) + if err != nil { + s.error(err) + return "", err + } + galleryImageVersion := compute.GalleryImageVersion{ Location: &location, Tags: tags, @@ -83,10 +103,11 @@ func (s *StepPublishToSharedImageGallery) publishToSig(ctx context.Context, mdiI ID: &mdiID, }, }, - TargetRegions: &replicationRegions, - EndOfLifeDate: endOfLifeDate, - ExcludeFromLatest: &miSGImageVersionExcludeFromLatest, - ReplicaCount: &miSigReplicaCount, + TargetRegions: &replicationRegions, + EndOfLifeDate: endOfLifeDate, + ExcludeFromLatest: &miSGImageVersionExcludeFromLatest, + ReplicaCount: &miSigReplicaCount, + StorageAccountType: storageAccountType, }, }, } @@ -149,6 +170,7 @@ func (s *StepPublishToSharedImageGallery) Run(ctx context.Context, stateBag mult s.say(fmt.Sprintf(" -> SIG image name : '%s'", sharedImageGallery.SigDestinationImageName)) s.say(fmt.Sprintf(" -> SIG image version : '%s'", sharedImageGallery.SigDestinationImageVersion)) s.say(fmt.Sprintf(" -> SIG replication regions : '%v'", sharedImageGallery.SigDestinationReplicationRegions)) + s.say(fmt.Sprintf(" -> SIG storage account type : '%s'", sharedImageGallery.SigDestinationStorageAccountType)) s.say(fmt.Sprintf(" -> SIG image version endoflife date : '%s'", miSGImageVersionEndOfLifeDate)) s.say(fmt.Sprintf(" -> SIG image version exclude from latest : '%t'", miSGImageVersionExcludeFromLatest)) s.say(fmt.Sprintf(" -> SIG replica count [1, 10] : '%d'", miSigReplicaCount)) diff --git a/builder/azure/arm/step_publish_to_shared_image_gallery_test.go b/builder/azure/arm/step_publish_to_shared_image_gallery_test.go index 42e92c419..87d636931 100644 --- a/builder/azure/arm/step_publish_to_shared_image_gallery_test.go +++ b/builder/azure/arm/step_publish_to_shared_image_gallery_test.go @@ -64,6 +64,7 @@ func createTestStateBagStepPublishToSharedImageGallery() multistep.StateBag { } stateBag.Put(constants.ArmTags, tags) stateBag.Put(constants.ArmManagedImageSharedGalleryReplicationRegions, []string{"ManagedImageSharedGalleryReplicationRegionA", "ManagedImageSharedGalleryReplicationRegionB"}) + stateBag.Put(constants.ArmManagedImageSharedGalleryImageVersionStorageAccountType, "Standard_LRS") stateBag.Put(constants.ArmManagedImageResourceGroupName, "Unit Test: ManagedImageResourceGroupName") stateBag.Put(constants.ArmManagedImageName, "Unit Test: ManagedImageName") stateBag.Put(constants.ArmManagedImageSubscription, "Unit Test: ManagedImageSubscription") diff --git a/builder/azure/common/constants/stateBag.go b/builder/azure/common/constants/stateBag.go index 948bbf67b..8a8ba1de6 100644 --- a/builder/azure/common/constants/stateBag.go +++ b/builder/azure/common/constants/stateBag.go @@ -17,42 +17,42 @@ const ( ) const ( - ArmCaptureTemplate string = "arm.CaptureTemplate" - ArmComputeName string = "arm.ComputeName" - ArmImageParameters string = "arm.ImageParameters" - ArmCertificateUrl string = "arm.CertificateUrl" - ArmKeyVaultDeploymentName string = "arm.KeyVaultDeploymentName" - ArmDeploymentName string = "arm.DeploymentName" - ArmNicName string = "arm.NicName" - ArmKeyVaultName string = "arm.KeyVaultName" - ArmLocation string = "arm.Location" - ArmOSDiskVhd string = "arm.OSDiskVhd" - ArmAdditionalDiskVhds string = "arm.AdditionalDiskVhds" - ArmPublicIPAddressName string = "arm.PublicIPAddressName" - ArmResourceGroupName string = "arm.ResourceGroupName" - ArmIsResourceGroupCreated string = "arm.IsResourceGroupCreated" - ArmDoubleResourceGroupNameSet string = "arm.DoubleResourceGroupNameSet" - ArmStorageAccountName string = "arm.StorageAccountName" - ArmTags string = "arm.Tags" - ArmVirtualMachineCaptureParameters string = "arm.VirtualMachineCaptureParameters" - ArmIsExistingResourceGroup string = "arm.IsExistingResourceGroup" - ArmIsExistingKeyVault string = "arm.IsExistingKeyVault" - - ArmIsManagedImage string = "arm.IsManagedImage" - ArmManagedImageResourceGroupName string = "arm.ManagedImageResourceGroupName" - ArmManagedImageName string = "arm.ManagedImageName" - ArmManagedImageSigPublishResourceGroup string = "arm.ManagedImageSigPublishResourceGroup" - ArmManagedImageSharedGalleryName string = "arm.ManagedImageSharedGalleryName" - ArmManagedImageSharedGalleryImageName string = "arm.ManagedImageSharedGalleryImageName" - ArmManagedImageSharedGalleryImageVersion string = "arm.ManagedImageSharedGalleryImageVersion" - ArmManagedImageSharedGalleryReplicationRegions string = "arm.ManagedImageSharedGalleryReplicationRegions" - ArmManagedImageSharedGalleryId string = "arm.ArmManagedImageSharedGalleryId" - ArmManagedImageSharedGalleryImageVersionEndOfLifeDate string = "arm.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate" - ArmManagedImageSharedGalleryImageVersionReplicaCount string = "arm.ArmManagedImageSharedGalleryImageVersionReplicaCount" - ArmManagedImageSharedGalleryImageVersionExcludeFromLatest string = "arm.ArmManagedImageSharedGalleryImageVersionExcludeFromLatest" - ArmManagedImageSubscription string = "arm.ArmManagedImageSubscription" - ArmAsyncResourceGroupDelete string = "arm.AsyncResourceGroupDelete" - ArmManagedImageOSDiskSnapshotName string = "arm.ManagedImageOSDiskSnapshotName" - ArmManagedImageDataDiskSnapshotPrefix string = "arm.ManagedImageDataDiskSnapshotPrefix" - ArmKeepOSDisk string = "arm.KeepOSDisk" + ArmCaptureTemplate string = "arm.CaptureTemplate" + ArmComputeName string = "arm.ComputeName" + ArmImageParameters string = "arm.ImageParameters" + ArmCertificateUrl string = "arm.CertificateUrl" + ArmKeyVaultDeploymentName string = "arm.KeyVaultDeploymentName" + ArmDeploymentName string = "arm.DeploymentName" + ArmNicName string = "arm.NicName" + ArmKeyVaultName string = "arm.KeyVaultName" + ArmLocation string = "arm.Location" + ArmOSDiskVhd string = "arm.OSDiskVhd" + ArmAdditionalDiskVhds string = "arm.AdditionalDiskVhds" + ArmPublicIPAddressName string = "arm.PublicIPAddressName" + ArmResourceGroupName string = "arm.ResourceGroupName" + ArmIsResourceGroupCreated string = "arm.IsResourceGroupCreated" + ArmDoubleResourceGroupNameSet string = "arm.DoubleResourceGroupNameSet" + ArmStorageAccountName string = "arm.StorageAccountName" + ArmTags string = "arm.Tags" + ArmVirtualMachineCaptureParameters string = "arm.VirtualMachineCaptureParameters" + ArmIsExistingResourceGroup string = "arm.IsExistingResourceGroup" + ArmIsExistingKeyVault string = "arm.IsExistingKeyVault" + ArmIsManagedImage string = "arm.IsManagedImage" + ArmManagedImageResourceGroupName string = "arm.ManagedImageResourceGroupName" + ArmManagedImageName string = "arm.ManagedImageName" + ArmManagedImageSigPublishResourceGroup string = "arm.ManagedImageSigPublishResourceGroup" + ArmManagedImageSharedGalleryName string = "arm.ManagedImageSharedGalleryName" + ArmManagedImageSharedGalleryImageName string = "arm.ManagedImageSharedGalleryImageName" + ArmManagedImageSharedGalleryImageVersion string = "arm.ManagedImageSharedGalleryImageVersion" + ArmManagedImageSharedGalleryReplicationRegions string = "arm.ManagedImageSharedGalleryReplicationRegions" + ArmManagedImageSharedGalleryId string = "arm.ArmManagedImageSharedGalleryId" + ArmManagedImageSharedGalleryImageVersionEndOfLifeDate string = "arm.ArmManagedImageSharedGalleryImageVersionEndOfLifeDate" + ArmManagedImageSharedGalleryImageVersionReplicaCount string = "arm.ArmManagedImageSharedGalleryImageVersionReplicaCount" + ArmManagedImageSharedGalleryImageVersionExcludeFromLatest string = "arm.ArmManagedImageSharedGalleryImageVersionExcludeFromLatest" + ArmManagedImageSharedGalleryImageVersionStorageAccountType string = "arm.ArmManagedImageSharedGalleryImageVersionStorageAccountType" + ArmManagedImageSubscription string = "arm.ArmManagedImageSubscription" + ArmAsyncResourceGroupDelete string = "arm.AsyncResourceGroupDelete" + ArmManagedImageOSDiskSnapshotName string = "arm.ManagedImageOSDiskSnapshotName" + ArmManagedImageDataDiskSnapshotPrefix string = "arm.ManagedImageDataDiskSnapshotPrefix" + ArmKeepOSDisk string = "arm.KeepOSDisk" ) diff --git a/website/content/partials/builder/azure/arm/Config-not-required.mdx b/website/content/partials/builder/azure/arm/Config-not-required.mdx index eec1fe16c..7ccb714c5 100644 --- a/website/content/partials/builder/azure/arm/Config-not-required.mdx +++ b/website/content/partials/builder/azure/arm/Config-not-required.mdx @@ -54,7 +54,8 @@ "gallery_name": "GalleryName", "image_name": "ImageName", "image_version": "1.0.0", - "replication_regions": ["regionA", "regionB", "regionC"] + "replication_regions": ["regionA", "regionB", "regionC"], + "storage_account_type": "Standard_LRS" } "managed_image_name": "TargetImageName", "managed_image_resource_group_name": "TargetResourceGroup" @@ -68,6 +69,7 @@ image_name = "ImageName" image_version = "1.0.0" replication_regions = ["regionA", "regionB", "regionC"] + storage_account_type = "Standard_LRS" } managed_image_name = "TargetImageName" managed_image_resource_group_name = "TargetResourceGroup" diff --git a/website/content/partials/builder/azure/arm/SharedImageGalleryDestination-not-required.mdx b/website/content/partials/builder/azure/arm/SharedImageGalleryDestination-not-required.mdx index 085ed5e13..53d413431 100644 --- a/website/content/partials/builder/azure/arm/SharedImageGalleryDestination-not-required.mdx +++ b/website/content/partials/builder/azure/arm/SharedImageGalleryDestination-not-required.mdx @@ -12,4 +12,7 @@ - `replication_regions` ([]string) - Sig Destination Replication Regions +- `storage_account_type` (string) - Specify a storage account type for the Shared Image Gallery Image Version. + Defaults to `Standard_LRS`. Accepted values are `Standard_LRS` and `Standard_ZRS` +