diff --git a/internal/services/azurestackhci/registration.go b/internal/services/azurestackhci/registration.go index e5729468fe4d..73906094776c 100644 --- a/internal/services/azurestackhci/registration.go +++ b/internal/services/azurestackhci/registration.go @@ -54,6 +54,7 @@ func (r Registration) Resources() []sdk.Resource { StackHCIExtensionResource{}, StackHCIDeploymentSettingResource{}, StackHCILogicalNetworkResource{}, + StackHCIMarketplaceGalleryImageResource{}, StackHCIStoragePathResource{}, StackHCIVirtualHardDiskResource{}, } diff --git a/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource.go b/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource.go new file mode 100644 index 000000000000..cbd2226f5cfe --- /dev/null +++ b/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource.go @@ -0,0 +1,330 @@ +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/marketplacegalleryimages" + "github.com/hashicorp/go-azure-sdk/resource-manager/azurestackhci/2024-01-01/storagecontainers" + "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 = StackHCIMarketplaceGalleryImageResource{} + _ sdk.ResourceWithUpdate = StackHCIMarketplaceGalleryImageResource{} +) + +type StackHCIMarketplaceGalleryImageResource struct{} + +func (StackHCIMarketplaceGalleryImageResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return marketplacegalleryimages.ValidateMarketplaceGalleryImageID +} + +func (StackHCIMarketplaceGalleryImageResource) ResourceType() string { + return "azurerm_stack_hci_marketplace_gallery_image" +} + +func (StackHCIMarketplaceGalleryImageResource) ModelObject() interface{} { + return &StackHCIMarketplaceGalleryImageResourceModel{} +} + +type StackHCIMarketplaceGalleryImageResourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + CustomLocationId string `tfschema:"custom_location_id"` + HypervGeneration string `tfschema:"hyperv_generation"` + Identifier []StackHCIMarketplaceGalleryImageIdentifier `tfschema:"identifier"` + OsType string `tfschema:"os_type"` + Version string `tfschema:"version"` + StoragePathId string `tfschema:"storage_path_id"` + Tags map[string]interface{} `tfschema:"tags"` +} + +type StackHCIMarketplaceGalleryImageIdentifier struct { + Offer string `tfschema:"offer"` + Publisher string `tfschema:"publisher"` + Sku string `tfschema:"sku"` +} + +func (StackHCIMarketplaceGalleryImageResource) 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,78}[a-zA-Z0-9]$`), + "name must be between 2 and 80 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{}), + + "hyperv_generation": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(marketplacegalleryimages.PossibleValuesForHyperVGeneration(), false), + }, + + "identifier": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "publisher": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "offer": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "sku": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + + "os_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(marketplacegalleryimages.PossibleValuesForOperatingSystemTypes(), false), + }, + + "version": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_path_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: storagecontainers.ValidateStorageContainerID, + }, + + "tags": commonschema.Tags(), + } +} + +func (StackHCIMarketplaceGalleryImageResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r StackHCIMarketplaceGalleryImageResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 3 * time.Hour, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.MarketplaceGalleryImages + + var config StackHCIMarketplaceGalleryImageResourceModel + if err := metadata.Decode(&config); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + subscriptionId := metadata.Client.Account.SubscriptionId + id := marketplacegalleryimages.NewMarketplaceGalleryImageID(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 := marketplacegalleryimages.MarketplaceGalleryImages{ + Name: pointer.To(config.Name), + Location: location.Normalize(config.Location), + Tags: tags.Expand(config.Tags), + ExtendedLocation: &marketplacegalleryimages.ExtendedLocation{ + Name: pointer.To(config.CustomLocationId), + Type: pointer.To(marketplacegalleryimages.ExtendedLocationTypesCustomLocation), + }, + Properties: &marketplacegalleryimages.MarketplaceGalleryImageProperties{ + Identifier: expandStackHCIMarketplaceGalleryImageIdentifier(config.Identifier), + OsType: marketplacegalleryimages.OperatingSystemTypes(config.OsType), + HyperVGeneration: pointer.To(marketplacegalleryimages.HyperVGeneration(config.HypervGeneration)), + Version: &marketplacegalleryimages.GalleryImageVersion{ + Name: pointer.To(config.Version), + }, + }, + } + + if config.StoragePathId != "" { + payload.Properties.ContainerId = pointer.To(config.StoragePathId) + } + + 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 StackHCIMarketplaceGalleryImageResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.MarketplaceGalleryImages + + id, err := marketplacegalleryimages.ParseMarketplaceGalleryImageID(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 := StackHCIMarketplaceGalleryImageResourceModel{ + Name: id.MarketplaceGalleryImageName, + 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.StoragePathId = pointer.From(props.ContainerId) + schema.OsType = string(props.OsType) + schema.HypervGeneration = string(pointer.From(props.HyperVGeneration)) + schema.Identifier = flattenStackHCIMarketplaceGalleryImageIdentifier(props.Identifier) + + if props.Version != nil { + schema.Version = pointer.From(props.Version.Name) + } + } + + } + return metadata.Encode(&schema) + }, + } +} + +func (r StackHCIMarketplaceGalleryImageResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.MarketplaceGalleryImages + + id, err := marketplacegalleryimages.ParseMarketplaceGalleryImageID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var model StackHCIMarketplaceGalleryImageResourceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + parameters := &marketplacegalleryimages.MarketplaceGalleryImagesUpdateRequest{} + 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 StackHCIMarketplaceGalleryImageResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 1 * time.Hour, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.AzureStackHCI.MarketplaceGalleryImages + + id, err := marketplacegalleryimages.ParseMarketplaceGalleryImageID(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 + }, + } +} + +func expandStackHCIMarketplaceGalleryImageIdentifier(input []StackHCIMarketplaceGalleryImageIdentifier) *marketplacegalleryimages.GalleryImageIdentifier { + if len(input) == 0 { + return nil + } + + v := input[0] + + return &marketplacegalleryimages.GalleryImageIdentifier{ + Offer: v.Offer, + Publisher: v.Publisher, + Sku: v.Sku, + } +} + +func flattenStackHCIMarketplaceGalleryImageIdentifier(input *marketplacegalleryimages.GalleryImageIdentifier) []StackHCIMarketplaceGalleryImageIdentifier { + if input == nil { + return make([]StackHCIMarketplaceGalleryImageIdentifier, 0) + } + + return []StackHCIMarketplaceGalleryImageIdentifier{ + { + Offer: input.Offer, + Publisher: input.Publisher, + Sku: input.Sku, + }, + } +} diff --git a/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource_test.go b/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource_test.go new file mode 100644 index 000000000000..0b42275f6f51 --- /dev/null +++ b/internal/services/azurestackhci/stack_hci_marketplace_gallery_image_resource_test.go @@ -0,0 +1,325 @@ +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/marketplacegalleryimages" + "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 StackHCIMarketplaceGalleryImageResource struct { + // az vm image list --all --output table --sku 2022-datacenter-azure-edition-core + imageVersion string +} + +func TestAccStackHCIMarketplaceGalleryImage_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_marketplace_gallery_image", "test") + r := StackHCIMarketplaceGalleryImageResource{ + imageVersion: "20348.2402.240607", + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIMarketplaceGalleryImage_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_marketplace_gallery_image", "test") + r := StackHCIMarketplaceGalleryImageResource{ + imageVersion: "20348.2582.240703", + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIMarketplaceGalleryImage_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_marketplace_gallery_image", "test") + r := StackHCIMarketplaceGalleryImageResource{ + imageVersion: "20348.2655.240810", + } + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.updateNoTag(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.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.updateNoTag(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStackHCIMarketplaceGalleryImage_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_marketplace_gallery_image", "test") + r := StackHCIMarketplaceGalleryImageResource{ + imageVersion: "20348.2655.240905", + } + + 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 StackHCIMarketplaceGalleryImageResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + clusterClient := client.AzureStackHCI.MarketplaceGalleryImages + id, err := marketplacegalleryimages.ParseMarketplaceGalleryImageID(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 StackHCIMarketplaceGalleryImageResource) basic(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s + +provider "azurerm" { + features {} +} + +resource "azurerm_stack_hci_marketplace_gallery_image" "test" { + name = "acctest-mgi-%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %q + hyperv_generation = "V2" + os_type = "Windows" + version = "%s" + identifier { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + } + + depends_on = [azurerm_role_assignment.test] +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv), r.imageVersion) +} + +func (r StackHCIMarketplaceGalleryImageResource) requiresImport(data acceptance.TestData) string { + config := r.basic(data) + + return fmt.Sprintf(` +%s + +resource "azurerm_stack_hci_marketplace_gallery_image" "import" { + name = azurerm_stack_hci_marketplace_gallery_image.test.name + resource_group_name = azurerm_stack_hci_marketplace_gallery_image.test.resource_group_name + location = azurerm_stack_hci_marketplace_gallery_image.test.location + custom_location_id = azurerm_stack_hci_marketplace_gallery_image.test.custom_location_id + hyperv_generation = azurerm_stack_hci_marketplace_gallery_image.test.hyperv_generation + os_type = azurerm_stack_hci_marketplace_gallery_image.test.os_type + version = azurerm_stack_hci_marketplace_gallery_image.test.version + identifier { + publisher = azurerm_stack_hci_marketplace_gallery_image.test.identifier.0.publisher + offer = azurerm_stack_hci_marketplace_gallery_image.test.identifier.0.offer + sku = azurerm_stack_hci_marketplace_gallery_image.test.identifier.0.sku + } +} +`, config) +} + +func (r StackHCIMarketplaceGalleryImageResource) updateNoTag(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-mgi-%[2]s" +} + +resource "azurerm_stack_hci_marketplace_gallery_image" "test" { + name = "acctest-mgi-%[2]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %[3]q + hyperv_generation = "V2" + os_type = "Windows" + version = "%s" + storage_path_id = azurerm_stack_hci_storage_path.test.id + identifier { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv), r.imageVersion) +} + +func (r StackHCIMarketplaceGalleryImageResource) updateTag(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-mgi-%[2]s" +} + +resource "azurerm_stack_hci_marketplace_gallery_image" "test" { + name = "acctest-mgi-%[2]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %[3]q + hyperv_generation = "V2" + os_type = "Windows" + version = "%s" + storage_path_id = azurerm_stack_hci_storage_path.test.id + identifier { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + } + tags = { + foo = "bar" + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv), r.imageVersion) +} + +func (r StackHCIMarketplaceGalleryImageResource) 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-mgi-%[2]s" +} + +resource "azurerm_stack_hci_marketplace_gallery_image" "test" { + name = "acctest-mgi-%[2]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + custom_location_id = %[3]q + hyperv_generation = "V2" + os_type = "Windows" + version = "%s" + storage_path_id = azurerm_stack_hci_storage_path.test.id + identifier { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + } + tags = { + foo = "bar" + env = "test" + } +} +`, template, data.RandomString, os.Getenv(customLocationIdEnv), r.imageVersion) +} + +func (r StackHCIMarketplaceGalleryImageResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctest-hci-mgi-%s" + location = "%s" +} + +data "azurerm_client_config" "test" {} + +// service principal of 'Microsoft.AzureStackHCI Resource Provider' +data "azuread_service_principal" "hciRp" { + client_id = "1412d89f-b8a8-4111-b4fd-e82905cbd85d" +} + +resource "azurerm_role_assignment" "test" { + scope = azurerm_resource_group.test.id + role_definition_name = "Azure Connected Machine Resource Manager" + principal_id = data.azuread_service_principal.hciRp.object_id +} +`, data.RandomString, data.Locations.Primary) +} diff --git a/website/docs/r/stack_hci_marketplace_gallery_image.html.markdown b/website/docs/r/stack_hci_marketplace_gallery_image.html.markdown new file mode 100644 index 000000000000..f620edf9279c --- /dev/null +++ b/website/docs/r/stack_hci_marketplace_gallery_image.html.markdown @@ -0,0 +1,111 @@ +--- +subcategory: "Azure Stack HCI" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_stack_hci_marketplace_gallery_image" +description: |- + Manages an Azure Stack HCI Marketplace Gallery Image. +--- + +# azurerm_stack_hci_marketplace_gallery_image + +Manages an Azure Stack HCI Marketplace Gallery Image. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "examples" + location = "West Europe" +} + +data "azurerm_client_config" "example" {} + +// service principal of 'Microsoft.AzureStackHCI Resource Provider' +data "azuread_service_principal" "hciRp" { + client_id = "1412d89f-b8a8-4111-b4fd-e82905cbd85d" +} + +resource "azurerm_role_assignment" "example" { + scope = azurerm_resource_group.example.id + role_definition_name = "Azure Connected Machine Resource Manager" + principal_id = data.azuread_service_principal.hciRp.object_id +} + +resource "azurerm_stack_hci_marketplace_gallery_image" "example" { + name = "example-mgi" + 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" + hyperv_generation = "V2" + os_type = "Windows" + version = "20348.2655.240905" + identifier { + publisher = "MicrosoftWindowsServer" + offer = "WindowsServer" + sku = "2022-datacenter-azure-edition-core" + } + tags = { + foo = "bar" + env = "example" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for this Azure Stack HCI Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Azure Stack HCI Marketplace Gallery Image should exist. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `location` - (Required) The Azure Region where the Azure Stack HCI Marketplace Gallery Image should exist. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `custom_location_id` - (Required) The ID of the Custom Location where the Azure Stack HCI Marketplace Gallery Image should exist. Changing this forces a new resource to be created. + +* `hyperv_generation` - (Required) The hypervisor generation of the Azure Stack HCI Marketplace Gallery Image. Possible values are `V1` and `V2`. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `identifier` - (Required) An `identifier` block as defined below. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `os_type` - (Required) The Operating System type of the Azure Stack HCI Marketplace Gallery Image. Possible values are `Windows` and `Linux`. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `version` - (Required) The version of the Azure Stack HCI Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +--- + +* `storage_path_id` - (Optional) The ID of the Azure Stack HCI Storage Path used for this Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Virtual Hard Disk to be created. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Azure Stack HCI Marketplace Gallery Image. + +--- + +An `identifier` block supports the following: + +* `offer` - (Required) The offer of the Azure Stack HCI Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `publisher` - (Required) The publisher of the Azure Stack HCI Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +* `sku` - (Required) The sku of the Azure Stack HCI Marketplace Gallery Image. Changing this forces a new Azure Stack HCI Marketplace Gallery Image to be created. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Azure Stack HCI Marketplace Gallery Image. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 3 hours) Used when creating the Azure Stack HCI Marketplace Gallery Image. +* `read` - (Defaults to 5 minutes) Used when retrieving the Azure Stack HCI Marketplace Gallery Image. +* `update` - (Defaults to 30 minutes) Used when updating the Azure Stack HCI Marketplace Gallery Image. +* `delete` - (Defaults to 1 hour) Used when deleting the Azure Stack HCI Marketplace Gallery Image. + +## Import + +Azure Stack HCI Marketplace Gallery Images can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_stack_hci_marketplace_gallery_image.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg1/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/image1 +```