diff --git a/internal/services/azurestackhci/registration.go b/internal/services/azurestackhci/registration.go index 188d28b0e618..bc417dbaf9e1 100644 --- a/internal/services/azurestackhci/registration.go +++ b/internal/services/azurestackhci/registration.go @@ -54,5 +54,6 @@ func (r Registration) Resources() []sdk.Resource { StackHCIDeploymentSettingResource{}, StackHCILogicalNetworkResource{}, StackHCIStoragePathResource{}, + StackHCIVirtualHardDiskResource{}, } } diff --git a/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource.go b/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource.go new file mode 100644 index 000000000000..4c4c7ed1e95f --- /dev/null +++ b/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource.go @@ -0,0 +1,321 @@ +package azurestackhci + +import ( + "context" + "fmt" + "regexp" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/azurestackhci/2024-01-01/storagecontainers" + "github.com/hashicorp/go-azure-sdk/resource-manager/azurestackhci/2024-01-01/virtualharddisks" + "github.com/hashicorp/go-azure-sdk/resource-manager/extendedlocation/2021-08-15/customlocations" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +var ( + _ sdk.Resource = StackHCIVirtualHardDiskResource{} + _ sdk.ResourceWithUpdate = StackHCIVirtualHardDiskResource{} +) + +type StackHCIVirtualHardDiskResource struct{} + +func (StackHCIVirtualHardDiskResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return virtualharddisks.ValidateVirtualHardDiskID +} + +func (StackHCIVirtualHardDiskResource) ResourceType() string { + return "azurerm_stack_hci_virtual_hard_disk" +} + +func (StackHCIVirtualHardDiskResource) ModelObject() interface{} { + return &StackHCIVirtualHardDiskResourceModel{} +} + +type StackHCIVirtualHardDiskResourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + CustomLocationId string `tfschema:"custom_location_id"` + BlockSizeInBytes int64 `tfschema:"block_size_in_bytes"` + DiskFileFormat string `tfschema:"disk_file_format"` + DiskSizeInGB int64 `tfschema:"disk_size_in_gb"` + DynamicEnabled bool `tfschema:"dynamic_enabled"` + HypervGeneration string `tfschema:"hyperv_generation"` + LogicalSectorInBytes int64 `tfschema:"logical_sector_in_bytes"` + PhysicalSectorInBytes int64 `tfschema:"physical_sector_in_bytes"` + StoragePathId string `tfschema:"storage_path_id"` + Tags map[string]interface{} `tfschema:"tags"` +} + +func (StackHCIVirtualHardDiskResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile(`^[a-zA-Z0-9][-._a-zA-Z0-9]{0,62}[a-zA-Z0-9]$`), + "name must be between 2 and 64 characters and can only contain alphanumberic characters, hyphen, dot and underline", + ), + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "location": commonschema.Location(), + + "custom_location_id": commonschema.ResourceIDReferenceRequiredForceNew(&customlocations.CustomLocationId{}), + + "block_size_in_bytes": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(1), + }, + + "disk_file_format": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(virtualharddisks.DiskFileFormatVhd), + string(virtualharddisks.DiskFileFormatVhdx), + }, false), + }, + + "disk_size_in_gb": { + Type: pluginsdk.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(1), + }, + + "dynamic_enabled": { + Type: pluginsdk.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + }, + + "hyperv_generation": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(virtualharddisks.HyperVGenerationVOne), + string(virtualharddisks.HyperVGenerationVTwo), + }, false), + }, + + "logical_sector_in_bytes": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(1), + }, + + "physical_sector_in_bytes": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(1), + }, + + "storage_path_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: storagecontainers.ValidateStorageContainerID, + }, + + "tags": commonschema.Tags(), + } +} + +func (StackHCIVirtualHardDiskResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r StackHCIVirtualHardDiskResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.VirtualHardDisks + + var config StackHCIVirtualHardDiskResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + subscriptionId := metadata.Client.Account.SubscriptionId + id := virtualharddisks.NewVirtualHardDiskID(subscriptionId, config.ResourceGroupName, config.Name) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + payload := virtualharddisks.VirtualHardDisks{ + Name: pointer.To(config.Name), + Location: location.Normalize(config.Location), + Tags: tags.Expand(config.Tags), + ExtendedLocation: &virtualharddisks.ExtendedLocation{ + Name: pointer.To(config.CustomLocationId), + Type: pointer.To(virtualharddisks.ExtendedLocationTypesCustomLocation), + }, + Properties: &virtualharddisks.VirtualHardDiskProperties{ + Dynamic: pointer.To(config.DynamicEnabled), + }, + } + + if config.BlockSizeInBytes != 0 { + payload.Properties.BlockSizeBytes = pointer.To(config.BlockSizeInBytes) + } + + if config.StoragePathId != "" { + payload.Properties.ContainerId = pointer.To(config.StoragePathId) + } + + if config.DiskFileFormat != "" { + payload.Properties.DiskFileFormat = pointer.To(virtualharddisks.DiskFileFormat(config.DiskFileFormat)) + } + + if config.DiskSizeInGB != 0 { + payload.Properties.DiskSizeGB = pointer.To(config.DiskSizeInGB) + } + + if config.HypervGeneration != "" { + payload.Properties.HyperVGeneration = pointer.To(virtualharddisks.HyperVGeneration(config.HypervGeneration)) + } + + if config.LogicalSectorInBytes != 0 { + payload.Properties.LogicalSectorBytes = pointer.To(config.LogicalSectorInBytes) + } + + if config.PhysicalSectorInBytes != 0 { + payload.Properties.PhysicalSectorBytes = pointer.To(config.PhysicalSectorInBytes) + } + + if err := client.CreateOrUpdateThenPoll(ctx, id, payload); err != nil { + return fmt.Errorf("performing create %s: %+v", id, err) + } + + metadata.SetID(id) + + return nil + }, + } +} + +func (r StackHCIVirtualHardDiskResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.VirtualHardDisks + + id, err := virtualharddisks.ParseVirtualHardDiskID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + schema := StackHCIVirtualHardDiskResourceModel{ + Name: id.VirtualHardDiskName, + ResourceGroupName: id.ResourceGroupName, + } + + if model := resp.Model; model != nil { + schema.Location = location.Normalize(model.Location) + schema.Tags = tags.Flatten(model.Tags) + + if model.ExtendedLocation != nil && model.ExtendedLocation.Name != nil { + customLocationId, err := customlocations.ParseCustomLocationIDInsensitively(*model.ExtendedLocation.Name) + if err != nil { + return err + } + + schema.CustomLocationId = customLocationId.ID() + } + + if props := model.Properties; props != nil { + schema.BlockSizeInBytes = pointer.From(props.BlockSizeBytes) + schema.DiskFileFormat = string(pointer.From(props.DiskFileFormat)) + schema.DiskSizeInGB = pointer.From(props.DiskSizeGB) + schema.DynamicEnabled = pointer.From(props.Dynamic) + schema.HypervGeneration = string(pointer.From(props.HyperVGeneration)) + schema.LogicalSectorInBytes = pointer.From(props.LogicalSectorBytes) + schema.PhysicalSectorInBytes = pointer.From(props.PhysicalSectorBytes) + schema.StoragePathId = pointer.From(props.ContainerId) + } + } + + return metadata.Encode(&schema) + }, + } +} + +func (r StackHCIVirtualHardDiskResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.VirtualHardDisks + + id, err := virtualharddisks.ParseVirtualHardDiskID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var model StackHCIVirtualHardDiskResourceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + parameters := virtualharddisks.VirtualHardDisksUpdateRequest{} + if metadata.ResourceData.HasChange("tags") { + parameters.Tags = tags.Expand(model.Tags) + } + + if err := client.UpdateThenPoll(ctx, *id, parameters); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + return nil + }, + } +} + +func (r StackHCIVirtualHardDiskResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.VirtualHardDisks + + id, err := virtualharddisks.ParseVirtualHardDiskID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) + } + + return nil + }, + } +} diff --git a/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource_test.go b/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource_test.go new file mode 100644 index 000000000000..c4480a43aec3 --- /dev/null +++ b/internal/services/azurestackhci/stack_hci_virtual_hard_disk_resource_test.go @@ -0,0 +1,265 @@ +package azurestackhci_test + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/azurestackhci/2024-01-01/virtualharddisks" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +type StackHCIVirtualHardDiskResource struct{} + +func TestAccStackHCIVirtualHardDisk_basic(t *testing.T) { + if os.Getenv(customLocationIdEnv) == "" { + t.Skipf("skipping since %q has not been specified", customLocationIdEnv) + } + + data := acceptance.BuildTestData(t, "azurerm_stack_hci_virtual_hard_disk", "test") + r := StackHCIVirtualHardDiskResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIVirtualHardDisk_complete(t *testing.T) { + if os.Getenv(customLocationIdEnv) == "" { + t.Skipf("skipping since %q has not been specified", customLocationIdEnv) + } + + data := acceptance.BuildTestData(t, "azurerm_stack_hci_virtual_hard_disk", "test") + r := StackHCIVirtualHardDiskResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIVirtualHardDisk_update(t *testing.T) { + if os.Getenv(customLocationIdEnv) == "" { + t.Skipf("skipping since %q has not been specified", customLocationIdEnv) + } + + data := acceptance.BuildTestData(t, "azurerm_stack_hci_virtual_hard_disk", "test") + r := StackHCIVirtualHardDiskResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.updateTag(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIVirtualHardDisk_requiresImport(t *testing.T) { + if os.Getenv(customLocationIdEnv) == "" { + t.Skipf("skipping since %q has not been specified", customLocationIdEnv) + } + + data := acceptance.BuildTestData(t, "azurerm_stack_hci_virtual_hard_disk", "test") + r := StackHCIVirtualHardDiskResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func (r StackHCIVirtualHardDiskResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + clusterClient := client.AzureStackHCI.VirtualHardDisks + id, err := virtualharddisks.ParseVirtualHardDiskID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clusterClient.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) + } + + return pointer.To(resp.Model != nil), nil +} + +func (r StackHCIVirtualHardDiskResource) basic(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +provider "azurerm" { + features {} +} + +resource "azurerm_stack_hci_virtual_hard_disk" "test" { + name = "acctest-vhd-%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %q + disk_size_in_gb = 2 + + lifecycle { + ignore_changes = [storage_path_id] + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv)) +} + +func (r StackHCIVirtualHardDiskResource) update(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +provider "azurerm" { + features {} +} + +resource "azurerm_stack_hci_virtual_hard_disk" "test" { + name = "acctest-vhd-%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %q + disk_size_in_gb = 2 + + tags = { + foo = "bar" + } + + lifecycle { + ignore_changes = [storage_path_id] + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv)) +} + +func (r StackHCIVirtualHardDiskResource) updateTag(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +provider "azurerm" { + features {} +} + +resource "azurerm_stack_hci_virtual_hard_disk" "test" { + name = "acctest-vhd-%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %q + disk_size_in_gb = 2 + + tags = { + env = "test" + foo = "bar" + } + + lifecycle { + ignore_changes = [storage_path_id] + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv)) +} + +func (r StackHCIVirtualHardDiskResource) complete(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%[1]s + +provider "azurerm" { + features {} +} + +resource "azurerm_stack_hci_storage_path" "test" { + name = "acctest-sp-%[2]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %[3]q + path = "C:\\ClusterStorage\\UserStorage_2\\sp-%[2]s" +} + +resource "azurerm_stack_hci_virtual_hard_disk" "test" { + name = "acctest-vhd-%[2]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %[3]q + disk_size_in_gb = 2 + storage_path_id = azurerm_stack_hci_storage_path.test.id + + tags = { + foo = "bar" + env = "test" + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv)) +} + +func (r StackHCIVirtualHardDiskResource) requiresImport(data acceptance.TestData) string { + config := r.basic(data) + + return fmt.Sprintf(` +%s + +resource "azurerm_stack_hci_virtual_hard_disk" "import" { + name = azurerm_stack_hci_virtual_hard_disk.test.name + resource_group_name = azurerm_stack_hci_virtual_hard_disk.test.resource_group_name + location = azurerm_stack_hci_virtual_hard_disk.test.location + custom_location_id = azurerm_stack_hci_virtual_hard_disk.test.custom_location_id + disk_size_in_gb = azurerm_stack_hci_virtual_hard_disk.test.disk_size_in_gb +} +`, config) +} + +func (r StackHCIVirtualHardDiskResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctest-hci-vhd-%[2]s" + location = %[1]q +} +`, data.Locations.Primary, data.RandomString) +} diff --git a/website/docs/r/stack_hci_virtual_hard_disk.html.markdown b/website/docs/r/stack_hci_virtual_hard_disk.html.markdown new file mode 100644 index 000000000000..78aeddc8085c --- /dev/null +++ b/website/docs/r/stack_hci_virtual_hard_disk.html.markdown @@ -0,0 +1,99 @@ +--- +subcategory: "Azure Stack HCI" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_stack_hci_virtual_hard_disk" +description: |- + Manages an Azure Stack HCI Virtual Hard Disk. +--- + +# azurerm_stack_hci_virtual_hard_disk + +Manages an Azure Stack HCI Virtual Hard Disk. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-rg" + location = "West Europe" +} + +resource "azurerm_stack_hci_storage_path" "example" { + name = "example-sp" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + custom_location_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ExtendedLocation/customLocations/cl1" + path = "C:\\ClusterStorage\\UserStorage_2\\sp-example" + tags = { + foo = "bar" + } +} + +resource "azurerm_stack_hci_virtual_hard_disk" "example" { + name = "example" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + custom_location_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.ExtendedLocation/customLocations/cl1" + storage_path_id = azurerm_stack_hci_storage_path.example.id + tags = { + foo = "bar" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for this Azure Stack HCI Virtual Hard Disk. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Azure Stack HCI Virtual Hard Disk should exist. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `location` - (Required) The Azure Region where the Azure Stack HCI Virtual Hard Disk should exist. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `custom_location_id` - (Required) The ID of the Custom Location where the Azure Stack HCI Virtual Hard Disk should exist. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `disk_size_in_gb` - (Required) The size of the disk in GB. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +--- + +* `block_size_in_bytes` - (Optional) The block size of the disk in bytes. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `disk_file_format` - (Optional) The format of the disk file. Possible values are `vhdx` and `vhd`. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `dynamic_enabled` - (Optional) Whether to enable dynamic sizing for the Azure Stack HCI Virtual Hard Disk. Defaults to `false`. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `hyperv_generation` - (Optional) The hypervisor generation of the Azure Stack HCI Virtual Hard Disk. Possible values are `V1` and `V2`. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `logical_sector_in_bytes` - (Optional) The logical sector size of the disk in bytes. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `physical_sector_in_bytes` - (Optional) The physical sector size of the disk in bytes. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `storage_path_id` - (Optional) The ID of the Azure Stack HCI Storage Path used for this Virtual Hard Disk. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +-> **Note:** If `storage_path_id` is not specified, the Virtual Hard Disk will be placed in a high availability Storage Path. If you experience a diff you may need to add this to `ignore_changes`. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Azure Stack HCI Virtual Hard Disk. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Azure Stack HCI Virtual Hard Disk. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Azure Stack HCI Virtual Hard Disk. +* `read` - (Defaults to 5 minutes) Used when retrieving the Azure Stack HCI Virtual Hard Disk. +* `update` - (Defaults to 30 minutes) Used when updating the Azure Stack HCI Virtual Hard Disk. +* `delete` - (Defaults to 30 minutes) Used when deleting the Azure Stack HCI Virtual Hard Disk. + +## Import + +Azure Stack HCI Virtual Hard Disks can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_stack_hci_virtual_hard_disk.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.AzureStackHCI/virtualHardDisks/disk1 +```