Skip to content

Commit

Permalink
azurerm_image: add option to set the hyper_v_generation for the image
Browse files Browse the repository at this point in the history
The new clients require this information see [properties.hyperVGeneration][1] and it supports 2 values `V1` and `V2` [2]

the default is `V1` in azure cli `--hyper-v-generation` [3], so it should be safe to keep that as default.

The testsuite before the change is as follows:

make testacc TESTARGS='-run=TestAccAzureRMImage_standaloneImage'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test $(go list ./... |grep -v 'vendor'|grep -v 'examples') -v -run=TestAccAzureRMImage_standaloneImage -timeout 180m -ldflags="-X=github.com/terraform-providers/terraform-provider-azurerm/version.ProviderVersion=acc"
?       github.com/terraform-providers/terraform-provider-azurerm       [no test files]

=== RUN   TestAccAzureRMImage_standaloneImage
=== PAUSE TestAccAzureRMImage_standaloneImage
=== RUN   TestAccAzureRMImage_standaloneImageZoneRedundant
=== PAUSE TestAccAzureRMImage_standaloneImageZoneRedundant
=== CONT  TestAccAzureRMImage_standaloneImage
=== CONT  TestAccAzureRMImage_standaloneImageZoneRedundant
--- FAIL: TestAccAzureRMImage_standaloneImageZoneRedundant (486.68s)
    testing.go:569: Step 0 error: errors during apply:

        Error: Code="PlatformImageNotFound" Message="The platform image 'Canonical:UbuntuServer:16.04-LTS:latest' is not available. Verify that all fields in the storage profile are correct."

          on /tmp/tf-test364164823/main.tf line 61:
          (source code not available)

--- FAIL: TestAccAzureRMImage_standaloneImage (1019.63s)
    testing.go:569: Step 1 error: errors during apply:

        Error: compute.ImagesClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidParameter" Message="Required parameter 'hyperVGeneration' is missing (null)." Target="hyperVGeneration"

          on /tmp/tf-test119634721/main.tf line 99:
          (source code not available)

        Error: Code="TargetDiskBlobAlreadyExists" Message="Blob https://accsa191001150912481015.blob.core.windows.net/vhds/myosdisk1.vhd already exists. Please provide a different blob URI as target for disk 'myosdisk1'."

          on /tmp/tf-test119634721/main.tf line 61:
          (source code not available)

FAIL
FAIL    github.com/terraform-providers/terraform-provider-azurerm/azurerm       1019.656s
```

The test suite after the change is as follows:

```console
make testacc TESTARGS='-run=^TestAccAzureRMImage_standaloneImage'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test $(go list ./... |grep -v 'vendor'|grep -v 'examples') -v -run=^TestAccAzureRMImage_standaloneImage -timeout 180m -ldflags="-X=github.com/terraform-providers/terraform-provider-azurerm/version.ProviderVersion=acc"
?       github.com/terraform-providers/terraform-provider-azurerm       [no test files]
=== RUN   TestAccAzureRMImage_standaloneImage
=== PAUSE TestAccAzureRMImage_standaloneImage
=== RUN   TestAccAzureRMImage_standaloneImage_hyperVGeneration_V2
=== PAUSE TestAccAzureRMImage_standaloneImage_hyperVGeneration_V2
=== RUN   TestAccAzureRMImage_standaloneImageZoneRedundant
=== PAUSE TestAccAzureRMImage_standaloneImageZoneRedundant
=== CONT  TestAccAzureRMImage_standaloneImage
=== CONT  TestAccAzureRMImage_standaloneImageZoneRedundant
=== CONT  TestAccAzureRMImage_standaloneImage_hyperVGeneration_V2
--- FAIL: TestAccAzureRMImage_standaloneImageZoneRedundant (362.47s)
    testing.go:569: Step 0 error: errors during apply:

        Error: Code="PlatformImageNotFound" Message="The platform image 'Canonical:UbuntuServer:18.04-LTS:latest' is not available. Verify that all fields in the storage profile are correct."

          on /tmp/tf-test403504907/main.tf line 61:
          (source code not available)

--- PASS: TestAccAzureRMImage_standaloneImage (380.55s)
--- PASS: TestAccAzureRMImage_standaloneImage_hyperVGeneration_V2 (564.15s)
FAIL
FAIL    github.com/terraform-providers/terraform-provider-azurerm/azurerm       564.181s
```

[1]: https://docs.microsoft.com/en-us/rest/api/compute/images/createorupdate#image
[2]: https://docs.microsoft.com/en-us/rest/api/compute/images/createorupdate#hypervgenerationtypes
[3]: https://docs.microsoft.com/en-us/cli/azure/image?view=azure-cli-latest#optional-parameters
  • Loading branch information
abhinavdahiya committed Oct 1, 2019
1 parent b803a22 commit 4134d92
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 14 deletions.
25 changes: 18 additions & 7 deletions azurerm/resource_arm_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ func resourceArmImage() *schema.Resource {
ForceNew: true,
},

"hyper_v_generation": {
Type: schema.TypeString,
Optional: true,
Default: string(compute.HyperVGenerationTypesV1),
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(compute.HyperVGenerationTypesV1),
string(compute.HyperVGenerationTypesV2),
}, false),
},

"source_virtual_machine_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -177,6 +188,7 @@ func resourceArmImageCreateUpdate(d *schema.ResourceData, meta interface{}) erro
name := d.Get("name").(string)
resGroup := d.Get("resource_group_name").(string)
zoneResilient := d.Get("zone_resilient").(bool)
hyperVGeneration := d.Get("hyper_v_generation").(string)

if features.ShouldResourcesBeImported() && d.IsNewResource() {
existing, err := client.Get(ctx, resGroup, name, "")
Expand All @@ -194,7 +206,9 @@ func resourceArmImageCreateUpdate(d *schema.ResourceData, meta interface{}) erro
location := azure.NormalizeLocation(d.Get("location").(string))
expandedTags := tags.Expand(d.Get("tags").(map[string]interface{}))

properties := compute.ImageProperties{}
properties := compute.ImageProperties{
HyperVGeneration: compute.HyperVGenerationTypes(hyperVGeneration),
}

osDisk, err := expandAzureRmImageOsDisk(d)
if err != nil {
Expand Down Expand Up @@ -227,14 +241,10 @@ func resourceArmImageCreateUpdate(d *schema.ResourceData, meta interface{}) erro
return fmt.Errorf("[ERROR] Cannot create image when both source VM and storage profile are empty")
}

properties = compute.ImageProperties{
StorageProfile: &storageProfile,
}
properties.StorageProfile = &storageProfile
} else {
//creating an image from source VM
properties = compute.ImageProperties{
SourceVirtualMachine: &sourceVM,
}
properties.SourceVirtualMachine = &sourceVM
}

createImage := compute.Image{
Expand Down Expand Up @@ -309,6 +319,7 @@ func resourceArmImageRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("zone_resilient", resp.StorageProfile.ZoneResilient)
}
d.Set("hyper_v_generation", string(resp.HyperVGeneration))

return tags.FlattenAndSet(d, resp.Tags)
}
Expand Down
58 changes: 52 additions & 6 deletions azurerm/resource_arm_image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,47 @@ func TestAccAzureRMImage_standaloneImage(t *testing.T) {
sshPort := "22"
location := testLocation()
preConfig := testAccAzureRMImage_standaloneImage_setup(ri, userName, password, hostName, location, "LRS")
postConfig := testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "LRS")
postConfig := testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "LRS", "")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMImageDestroy,
Steps: []resource.TestStep{
{
//need to create a vm and then reference it in the image creation
Config: preConfig,
Destroy: false,
Check: resource.ComposeTestCheckFunc(
testCheckAzureVMExists("azurerm_virtual_machine.testsource", true),
testGeneralizeVMImage(resourceGroup, "testsource", userName, password, hostName, sshPort, location),
),
},
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMImageExists("azurerm_image.test", true),
),
},
{
ResourceName: "azurerm_image.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMImage_standaloneImageHyperVGenerationV2(t *testing.T) {
ri := tf.AccRandTimeInt()
resourceGroup := fmt.Sprintf("acctestRG-%d", ri)
userName := "testadmin"
password := "Password1234!"
hostName := fmt.Sprintf("tftestcustomimagesrc%d", ri)
sshPort := "22"
location := testLocation()
preConfig := testAccAzureRMImage_standaloneImage_setup(ri, userName, password, hostName, location, "LRS")
postConfig := testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "LRS", "V2")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand Down Expand Up @@ -65,7 +105,7 @@ func TestAccAzureRMImage_standaloneImageZoneRedundant(t *testing.T) {
sshPort := "22"
location := testLocation()
preConfig := testAccAzureRMImage_standaloneImage_setup(ri, userName, password, hostName, location, "ZRS")
postConfig := testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "ZRS")
postConfig := testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "ZRS", "")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand Down Expand Up @@ -125,7 +165,7 @@ func TestAccAzureRMImage_requiresImport(t *testing.T) {
),
},
{
Config: testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "LRS"),
Config: testAccAzureRMImage_standaloneImage_provision(ri, userName, password, hostName, location, "LRS", ""),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMImageExists("azurerm_image.test", true),
),
Expand Down Expand Up @@ -539,7 +579,12 @@ resource "azurerm_virtual_machine" "testsource" {
`, rInt, location, rInt, rInt, rInt, hostName, rInt, rInt, storageType, userName, password)
}

func testAccAzureRMImage_standaloneImage_provision(rInt int, userName string, password string, hostName string, location string, storageType string) string {
func testAccAzureRMImage_standaloneImage_provision(rInt int, userName string, password string, hostName string, location string, storageType string, hyperVGen string) string {
hyperVGenAtt := ""
if hyperVGen != "" {
hyperVGenAtt = fmt.Sprintf(`hyper_v_generation = "%s"`, hyperVGen)
}

return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
Expand Down Expand Up @@ -643,6 +688,7 @@ resource "azurerm_image" "test" {
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
zone_resilient = %t
%s
os_disk {
os_type = "Linux"
Expand All @@ -657,11 +703,11 @@ resource "azurerm_image" "test" {
cost-center = "Ops"
}
}
`, rInt, location, rInt, rInt, rInt, hostName, rInt, rInt, storageType, userName, password, storageType == "ZRS")
`, rInt, location, rInt, rInt, rInt, hostName, rInt, rInt, storageType, userName, password, storageType == "ZRS", hyperVGenAtt)
}

func testAccAzureRMImage_standaloneImage_requiresImport(rInt int, userName string, password string, hostName string, location string) string {
template := testAccAzureRMImage_standaloneImage_provision(rInt, userName, password, hostName, location, "LRS")
template := testAccAzureRMImage_standaloneImage_provision(rInt, userName, password, hostName, location, "LRS", "")
return fmt.Sprintf(`
%s
Expand Down
2 changes: 1 addition & 1 deletion azurerm/resource_arm_shared_image_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func testAccAzureRMSharedImageVersion_setup(rInt int, location, username, passwo
}

func testAccAzureRMSharedImageVersion_provision(rInt int, location, username, password, hostname string) string {
template := testAccAzureRMImage_standaloneImage_provision(rInt, username, password, hostname, location, "LRS")
template := testAccAzureRMImage_standaloneImage_provision(rInt, username, password, hostname, location, "LRS", "")
return fmt.Sprintf(`
%s
Expand Down
1 change: 1 addition & 0 deletions website/docs/r/image.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ The following arguments are supported:
* `data_disk` - (Optional) One or more `data_disk` elements as defined below.
* `tags` - (Optional) A mapping of tags to assign to the resource.
* `zone_resilient` - (Optional) Is zone resiliency enabled? Defaults to `false`. Changing this forces a new resource to be created.
* `hyper_v_generation` - (Optional) The HyperVGenerationType of the VirtualMachine created from the image as `V1`, `V2`. The default is `V1`.

~> **Note**: `zone_resilient` can only be set to `true` if the image is stored in a region that supports availability zones.

Expand Down

0 comments on commit 4134d92

Please sign in to comment.