From 335feaf89ceae13d5009904c71f0404b2ccc3f0f Mon Sep 17 00:00:00 2001 From: mbearup Date: Tue, 9 Oct 2018 13:56:49 -0700 Subject: [PATCH] Convert shared_image_gallery options to a struct Updates tests and documentation for shared_image_gallery --- builder/azure/arm/config.go | 44 ++++++++++-------- builder/azure/arm/config_test.go | 46 ++++++++++--------- builder/azure/arm/template_factory.go | 14 +++--- .../common/template/template_builder_test.go | 43 +++++++++++++++++ website/source/docs/builders/azure.html.md | 13 ++++++ 5 files changed, 111 insertions(+), 49 deletions(-) diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go index a85d374ce..d72d28550 100644 --- a/builder/azure/arm/config.go +++ b/builder/azure/arm/config.go @@ -65,6 +65,14 @@ type PlanInformation struct { PlanPromotionCode string `mapstructure:"plan_promotion_code"` } +type SharedImageGallery struct { + Subscription string `mapstructure:"subscription"` + ResourceGroup string `mapstructure:"resource_group"` + GalleryName string `mapstructure:"gallery_name"` + ImageName string `mapstructure:"image_name"` + ImageVersion string `mapstructure:"image_version"` +} + type Config struct { common.PackerConfig `mapstructure:",squash"` @@ -80,11 +88,7 @@ type Config struct { CaptureContainerName string `mapstructure:"capture_container_name"` // Shared Gallery - SharedGallerySubscription string `mapstructure:"shared_gallery_subscription"` - SharedGalleryResourceGroup string `mapstructure:"shared_gallery_resource_group"` - SharedGalleryName string `mapstructure:"shared_gallery_name"` - SharedGalleryImageName string `mapstructure:"shared_gallery_image_name"` - SharedGalleryImageVersion string `mapstructure:"shared_gallery_image_version"` + SharedGallery SharedImageGallery `mapstructure:"shared_image_gallery"` // Compute ImagePublisher string `mapstructure:"image_publisher"` @@ -579,35 +583,35 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) { isImageUrl := c.ImageUrl != "" isCustomManagedImage := c.CustomManagedImageName != "" || c.CustomManagedImageResourceGroupName != "" - isSharedGallery := c.SharedGalleryName != "" + isSharedGallery := c.SharedGallery.GalleryName != "" isPlatformImage := c.ImagePublisher != "" || c.ImageOffer != "" || c.ImageSku != "" countSourceInputs := toInt(isImageUrl) + toInt(isCustomManagedImage) + toInt(isPlatformImage) + toInt(isSharedGallery) if countSourceInputs > 1 { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (image_url), Image Reference (image_publisher, image_offer, image_sku), a Managed Disk (custom_managed_disk_image_name, custom_managed_disk_resource_group_name), or a Shared Gallery Image (shared_gallery_subscription, shared_gallery_resource_group, shared_gallery_name, shared_gallery_image_name)")) + errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (image_url), Image Reference (image_publisher, image_offer, image_sku), a Managed Disk (custom_managed_disk_image_name, custom_managed_disk_resource_group_name), or a Shared Gallery Image (shared_image_gallery)")) } if isImageUrl && c.ManagedImageResourceGroupName != "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("A managed image must be created from a managed image, it cannot be created from a VHD.")) } - if c.SharedGalleryName != "" { - if c.SharedGallerySubscription == "" { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_gallery_subscription must be specified")) + if c.SharedGallery.GalleryName != "" { + if c.SharedGallery.Subscription == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_image_gallery.subscription must be specified")) } - if c.SharedGalleryResourceGroup == "" { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_gallery_resource_group must be specified")) + if c.SharedGallery.ResourceGroup == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_image_gallery.resource_group must be specified")) } - if c.SharedGalleryImageName == "" { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_gallery_image_name must be specified")) + if c.SharedGallery.ImageName == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("A shared_image_gallery.image_name must be specified")) + } + if c.CaptureContainerName != "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("VHD Target [capture_container_name] is not supported when using Shared Image Gallery as source. Use managed_image_resource_group_name instead.")) + } + if c.CaptureNamePrefix != "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("VHD Target [capture_name_prefix] is not supported when using Shared Image Gallery as source. Use managed_image_name instead.")) } - if c.CaptureContainerName != "" { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("VHD Target [capture_container_name] is not supported when using Shared Image Gallery as source. Use managed_image_resource_group_name instead.")) - } - if c.CaptureNamePrefix != "" { - errs = packer.MultiErrorAppend(errs, fmt.Errorf("VHD Target [capture_name_prefix] is not supported when using Shared Image Gallery as source. Use managed_image_name instead.")) - } } else if c.ImageUrl == "" && c.CustomManagedImageName == "" { if c.ImagePublisher == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("An image_publisher must be specified")) diff --git a/builder/azure/arm/config_test.go b/builder/azure/arm/config_test.go index 0801a8063..ac523a158 100644 --- a/builder/azure/arm/config_test.go +++ b/builder/azure/arm/config_test.go @@ -1297,15 +1297,16 @@ func TestConfigShouldAllowAsyncResourceGroupOverrideBadValue(t *testing.T) { } func TestConfigShouldAllowSharedImageGalleryOptions(t *testing.T) { config := map[string]interface{}{ - "location": "ignore", - "subscription_id": "ignore", - "os_type": "linux", - "shared_gallery_subscription": "ignore", - "shared_gallery_resource_group": "ignore", - "shared_gallery_resource_group": "ignore", - "shared_gallery_name": "ignore", - "shared_gallery_image_name": "ignore", - "shared_gallery_image_version": "ignore", + "location": "ignore", + "subscription_id": "ignore", + "os_type": "linux", + "shared_image_gallery": { + "subscription": "ignore", + "resource_group": "ignore", + "gallery_name": "ignore", + "image_name": "ignore", + "image_version": "ignore", + }, } c, _, err := newConfig(config, getPackerConfiguration()) @@ -1317,19 +1318,20 @@ func TestConfigShouldAllowSharedImageGalleryOptions(t *testing.T) { func TestConfigShouldRejectSharedImageGalleryWithVhdTarget(t *testing.T) { config := map[string]interface{}{ - "location": "ignore", - "subscription_id": "ignore", - "os_type": "linux", - "shared_gallery_subscription": "ignore", - "shared_gallery_resource_group": "ignore", - "shared_gallery_resource_group": "ignore", - "shared_gallery_name": "ignore", - "shared_gallery_image_name": "ignore", - "shared_gallery_image_version": "ignore", - "resource_group_name": "ignore", - "storage_account": "ignore", - "capture_container_name": "ignore", - "capture_name_prefix": "ignore", + "location": "ignore", + "subscription_id": "ignore", + "os_type": "linux", + "shared_image_gallery": { + "subscription": "ignore", + "resource_group": "ignore", + "gallery_name": "ignore", + "image_name": "ignore", + "image_version": "ignore", + }, + "resource_group_name": "ignore", + "storage_account": "ignore", + "capture_container_name": "ignore", + "capture_name_prefix": "ignore", } c, _, err := newConfig(config, getPackerConfiguration()) diff --git a/builder/azure/arm/template_factory.go b/builder/azure/arm/template_factory.go index fbc401bf4..00873e457 100644 --- a/builder/azure/arm/template_factory.go +++ b/builder/azure/arm/template_factory.go @@ -72,15 +72,15 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error) config.ImageVersion) builder.SetManagedMarketplaceImage(config.Location, config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion, imageID, config.managedImageStorageAccountType) - } else if config.SharedGallerySubscription != "" && config.SharedGalleryResourceGroup != "" && config.SharedGalleryName != "" && config.SharedGalleryImageName != "" { + } else if config.SharedGallery.Subscription != "" { imageID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/galleries/%s/images/%s", - config.SharedGallerySubscription, - config.SharedGalleryResourceGroup, - config.SharedGalleryName, - config.SharedGalleryImageName) - if config.SharedGalleryImageVersion != "" { + config.SharedGallery.Subscription, + config.SharedGallery.ResourceGroup, + config.SharedGallery.GalleryName, + config.SharedGallery.ImageName) + if config.SharedGallery.ImageVersion != "" { imageID += fmt.Sprintf("/versions/%s", - config.SharedGalleryImageVersion) + config.SharedGallery.ImageVersion) } builder.SetSharedGalleryImage(config.Location, imageID) diff --git a/builder/azure/common/template/template_builder_test.go b/builder/azure/common/template/template_builder_test.go index bc7baa175..9155cc65e 100644 --- a/builder/azure/common/template/template_builder_test.go +++ b/builder/azure/common/template/template_builder_test.go @@ -181,3 +181,46 @@ func TestBuildWindows02(t *testing.T) { t.Fatal(err) } } + +// Shared Image Gallery Build +func TestSharedIageGallery00(t *testing.T) { + testSubject, err := NewTemplateBuilder(BasicTemplate) + if err != nil { + t.Fatal(err) + } + + imageID := "/subscriptions/ignore/resourceGroups/ignore/providers/Microsoft.Compute/galleries/ignore/images/ignore" + err = testSubject.SetSharedGalleryImage("westcentralus", imageID) + if err != nil { + t.Fatal(err) + } + + doc, err := testSubject.ToJSON() + if err != nil { + t.Fatal(err) + } + + err = approvaltests.VerifyJSONBytes(t, []byte(*doc)) + if err != nil { + t.Fatal(err) + } + + if doc.variables.apiVersion != "2018-04-01" { + t.Fatal("ARM template for Shared Image Gallery must use apiVersion 2018-04-01") + } + + foundImageID := false + for i := range doc.resources { + if doc.resources[i]["type"] == "Microsoft.Compute/virtualMachines" { + storageProfile := doc.resources[i].properties.storageProfile + if storageProfile.ImageReference != imageID { + t.Fatal("ARM template for Shared Image Gallery must have a valid imageID in its storageProfile") + } + foundImageID = true + } + } + + if !foundImageID { + t.Fatal("ARM template for Shared Image Gallery must have a valid imageID in its storageProfile") + } +} diff --git a/website/source/docs/builders/azure.html.md b/website/source/docs/builders/azure.html.md index a4f3a7b09..ca6e82659 100644 --- a/website/source/docs/builders/azure.html.md +++ b/website/source/docs/builders/azure.html.md @@ -186,6 +186,19 @@ Providing `temp_resource_group_name` or `location` in combination with `build_re 1. PlanPublisher 1. PlanPromotionCode +- `shared_image_gallery` (object) Use a [Shared Gallery image](https://azure.microsoft.com/en-us/blog/announcing-the-public-preview-of-shared-image-gallery/) as the source for this build. *VHD targets are incompatible with this build type* - the target must be a *Managed Image*. +``` +"shared_image_gallery": { + "subscription": "00000000-0000-0000-0000-00000000000", + "resource_group": "ResourceGroup", + "gallery_name": "GalleryName", + "image_name": "ImageName", + "image_version": "1.0.0" +} +"managed_image_name": "TargetImageName", +"managed_image_resource_group_name": "TargetResourceGroup" +``` + - `temp_compute_name` (string) temporary name assigned to the VM. If this value is not set, a random value will be assigned. Knowing the resource group and VM name allows one to execute commands to update the VM during a Packer build, e.g. attach a resource disk to the VM.