diff --git a/internal/services/elasticsan/elastic_san_data_source.go b/internal/services/elasticsan/elastic_san_data_source.go new file mode 100644 index 000000000000..11fd44752c84 --- /dev/null +++ b/internal/services/elasticsan/elastic_san_data_source.go @@ -0,0 +1,167 @@ +package elasticsan + +import ( + "context" + "fmt" + "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-helpers/resourcemanager/zones" + "github.com/hashicorp/go-azure-sdk/resource-manager/elasticsan/2023-01-01/elasticsans" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/elasticsan/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +type ElasticSANDataSource struct{} + +var _ sdk.DataSource = ElasticSANDataSource{} + +type ElasticSANDataSourceModel struct { + BaseSizeInTiB int64 `tfschema:"base_size_in_tib"` + ExtendedSizeInTiB int64 `tfschema:"extended_size_in_tib"` + Location string `tfschema:"location"` + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Sku []ElasticSANResourceSkuModel `tfschema:"sku"` + Tags map[string]interface{} `tfschema:"tags"` + TotalIops int64 `tfschema:"total_iops"` + TotalMBps int64 `tfschema:"total_mbps"` + TotalSizeInTiB int64 `tfschema:"total_size_in_tib"` + TotalVolumeSizeInGiB int64 `tfschema:"total_volume_size_in_gib"` + VolumeGroupCount int64 `tfschema:"volume_group_count"` + Zones []string `tfschema:"zones"` +} + +func (r ElasticSANDataSource) ResourceType() string { + return "azurerm_elastic_san" +} + +func (r ElasticSANDataSource) ModelObject() interface{} { + return &ElasticSANDataSourceModel{} +} + +func (r ElasticSANDataSource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.ElasticSanName, + }, + + "resource_group_name": commonschema.ResourceGroupNameForDataSource(), + } +} + +func (r ElasticSANDataSource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "location": commonschema.LocationComputed(), + + "zones": commonschema.ZonesMultipleComputed(), + + "base_size_in_tib": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "extended_size_in_tib": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "sku": { + Computed: true, + Type: pluginsdk.TypeList, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Computed: true, + Type: pluginsdk.TypeString, + }, + + "tier": { + Computed: true, + Type: pluginsdk.TypeString, + }, + }, + }, + }, + + "total_iops": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "total_mbps": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "total_size_in_tib": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "total_volume_size_in_gib": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "volume_group_count": { + Computed: true, + Type: pluginsdk.TypeInt, + }, + + "tags": commonschema.TagsDataSource(), + } +} + +func (r ElasticSANDataSource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.ElasticSan.ElasticSans + subscriptionId := metadata.Client.Account.SubscriptionId + + var state ElasticSANDataSourceModel + if err := metadata.Decode(&state); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + id := elasticsans.NewElasticSanID(subscriptionId, state.ResourceGroupName, state.Name) + + resp, err := client.Get(ctx, id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("%s does not exist", id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + if model := resp.Model; model != nil { + state.Location = location.Normalize(model.Location) + state.Tags = tags.Flatten(model.Tags) + + prop := model.Properties + state.Sku = FlattenSku(prop.Sku) + state.Zones = zones.Flatten(prop.AvailabilityZones) + state.BaseSizeInTiB = prop.BaseSizeTiB + state.ExtendedSizeInTiB = prop.ExtendedCapacitySizeTiB + state.TotalIops = pointer.From(prop.TotalIops) + state.TotalMBps = pointer.From(prop.TotalMBps) + state.TotalSizeInTiB = pointer.From(prop.TotalSizeTiB) + state.TotalVolumeSizeInGiB = pointer.From(prop.TotalVolumeSizeGiB) + state.VolumeGroupCount = pointer.From(prop.VolumeGroupCount) + } + + metadata.SetID(id) + + return metadata.Encode(&state) + }, + } +} diff --git a/internal/services/elasticsan/elastic_san_data_source_test.go b/internal/services/elasticsan/elastic_san_data_source_test.go new file mode 100644 index 000000000000..223edc9ba20d --- /dev/null +++ b/internal/services/elasticsan/elastic_san_data_source_test.go @@ -0,0 +1,48 @@ +package elasticsan_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type ElasticSANDataSource struct{} + +func TestAccElasticSANDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_elastic_san", "test") + d := ElasticSANDataSource{} + + data.DataSourceTestInSequence(t, []acceptance.TestStep{ + { + Config: d.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("sku.#").HasValue("1"), + check.That(data.ResourceName).Key("sku.0.name").HasValue("Premium_LRS"), + check.That(data.ResourceName).Key("sku.0.tier").HasValue("Premium"), + check.That(data.ResourceName).Key("location").IsNotEmpty(), + check.That(data.ResourceName).Key("base_size_in_tib").HasValue("2"), + check.That(data.ResourceName).Key("extended_size_in_tib").HasValue("4"), + check.That(data.ResourceName).Key("zones.#").HasValue("2"), + check.That(data.ResourceName).Key("tags.%").HasValue("2"), + check.That(data.ResourceName).Key("total_iops").Exists(), + check.That(data.ResourceName).Key("total_mbps").Exists(), + check.That(data.ResourceName).Key("total_size_in_tib").Exists(), + check.That(data.ResourceName).Key("total_volume_size_in_gib").Exists(), + check.That(data.ResourceName).Key("volume_group_count").Exists(), + ), + }, + }) +} + +func (d ElasticSANDataSource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +data "azurerm_elastic_san" "test" { + name = azurerm_elastic_san.test.name + resource_group_name = azurerm_elastic_san.test.resource_group_name +} +`, ElasticSANTestResource{}.complete(data)) +} diff --git a/internal/services/elasticsan/elastic_san_resource.go b/internal/services/elasticsan/elastic_san_resource.go index 2213720b4715..397d03a900a0 100644 --- a/internal/services/elasticsan/elastic_san_resource.go +++ b/internal/services/elasticsan/elastic_san_resource.go @@ -21,9 +21,11 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) -var _ sdk.Resource = ElasticSANResource{} -var _ sdk.ResourceWithUpdate = ElasticSANResource{} -var _ sdk.ResourceWithCustomizeDiff = ElasticSANResource{} +var ( + _ sdk.Resource = ElasticSANResource{} + _ sdk.ResourceWithUpdate = ElasticSANResource{} + _ sdk.ResourceWithCustomizeDiff = ElasticSANResource{} +) type ElasticSANResource struct{} @@ -32,18 +34,18 @@ func (r ElasticSANResource) ModelObject() interface{} { } type ElasticSANResourceModel struct { - BaseSizeInTiB int `tfschema:"base_size_in_tib"` - ExtendedSizeInTiB int `tfschema:"extended_size_in_tib"` + BaseSizeInTiB int64 `tfschema:"base_size_in_tib"` + ExtendedSizeInTiB int64 `tfschema:"extended_size_in_tib"` Location string `tfschema:"location"` Name string `tfschema:"name"` ResourceGroupName string `tfschema:"resource_group_name"` Sku []ElasticSANResourceSkuModel `tfschema:"sku"` Tags map[string]interface{} `tfschema:"tags"` - TotalIops int `tfschema:"total_iops"` - TotalMBps int `tfschema:"total_mbps"` - TotalSizeInTiB int `tfschema:"total_size_in_tib"` - TotalVolumeSizeInGiB int `tfschema:"total_volume_size_in_gib"` - VolumeGroupCount int `tfschema:"volume_group_count"` + TotalIops int64 `tfschema:"total_iops"` + TotalMBps int64 `tfschema:"total_mbps"` + TotalSizeInTiB int64 `tfschema:"total_size_in_tib"` + TotalVolumeSizeInGiB int64 `tfschema:"total_volume_size_in_gib"` + VolumeGroupCount int64 `tfschema:"volume_group_count"` Zones []string `tfschema:"zones"` } @@ -205,8 +207,8 @@ func (r ElasticSANResource) Create() sdk.ResourceFunc { Location: location.Normalize(config.Location), Tags: tags.Expand(config.Tags), Properties: elasticsans.ElasticSanProperties{ - BaseSizeTiB: int64(config.BaseSizeInTiB), - ExtendedCapacitySizeTiB: int64(config.ExtendedSizeInTiB), + BaseSizeTiB: config.BaseSizeInTiB, + ExtendedCapacitySizeTiB: config.ExtendedSizeInTiB, Sku: ExpandSku(config.Sku), }, } @@ -230,7 +232,6 @@ func (r ElasticSANResource) Read() sdk.ResourceFunc { Timeout: 5 * time.Minute, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { client := metadata.Client.ElasticSan.ElasticSans - schema := ElasticSANResourceModel{} id, err := elasticsans.ParseElasticSanID(metadata.ResourceData.Id()) if err != nil { @@ -245,26 +246,28 @@ func (r ElasticSANResource) Read() sdk.ResourceFunc { return fmt.Errorf("retrieving %s: %+v", *id, err) } - schema.Name = id.ElasticSanName - schema.ResourceGroupName = id.ResourceGroupName + state := ElasticSANResourceModel{ + Name: id.ElasticSanName, + ResourceGroupName: id.ResourceGroupName, + } if model := resp.Model; model != nil { - schema.Location = location.Normalize(model.Location) - schema.Tags = tags.Flatten(model.Tags) + state.Location = location.Normalize(model.Location) + state.Tags = tags.Flatten(model.Tags) prop := model.Properties - schema.Sku = FlattenSku(prop.Sku) - schema.Zones = zones.Flatten(prop.AvailabilityZones) - schema.BaseSizeInTiB = int(prop.BaseSizeTiB) - schema.ExtendedSizeInTiB = int(prop.ExtendedCapacitySizeTiB) - schema.TotalIops = int(pointer.From(prop.TotalIops)) - schema.TotalMBps = int(pointer.From(prop.TotalMBps)) - schema.TotalSizeInTiB = int(pointer.From(prop.TotalSizeTiB)) - schema.TotalVolumeSizeInGiB = int(pointer.From(prop.TotalVolumeSizeGiB)) - schema.VolumeGroupCount = int(pointer.From(prop.VolumeGroupCount)) + state.Sku = FlattenSku(prop.Sku) + state.Zones = zones.Flatten(prop.AvailabilityZones) + state.BaseSizeInTiB = prop.BaseSizeTiB + state.ExtendedSizeInTiB = prop.ExtendedCapacitySizeTiB + state.TotalIops = pointer.From(prop.TotalIops) + state.TotalMBps = pointer.From(prop.TotalMBps) + state.TotalSizeInTiB = pointer.From(prop.TotalSizeTiB) + state.TotalVolumeSizeInGiB = pointer.From(prop.TotalVolumeSizeGiB) + state.VolumeGroupCount = pointer.From(prop.VolumeGroupCount) } - return metadata.Encode(&schema) + return metadata.Encode(&state) }, } } @@ -311,14 +314,14 @@ func (r ElasticSANResource) Update() sdk.ResourceFunc { if payload.Properties == nil { payload.Properties = &elasticsans.ElasticSanUpdateProperties{} } - payload.Properties.BaseSizeTiB = pointer.To(int64(config.BaseSizeInTiB)) + payload.Properties.BaseSizeTiB = pointer.To(config.BaseSizeInTiB) } if metadata.ResourceData.HasChange("extended_size_in_tib") { if payload.Properties == nil { payload.Properties = &elasticsans.ElasticSanUpdateProperties{} } - payload.Properties.ExtendedCapacitySizeTiB = pointer.To(int64(config.ExtendedSizeInTiB)) + payload.Properties.ExtendedCapacitySizeTiB = pointer.To(config.ExtendedSizeInTiB) } if metadata.ResourceData.HasChange("tags") { diff --git a/internal/services/elasticsan/registration.go b/internal/services/elasticsan/registration.go index e245aa82baba..d5d8f727a61a 100644 --- a/internal/services/elasticsan/registration.go +++ b/internal/services/elasticsan/registration.go @@ -18,7 +18,9 @@ func (Registration) Name() string { } func (Registration) DataSources() []sdk.DataSource { - return []sdk.DataSource{} + return []sdk.DataSource{ + ElasticSANDataSource{}, + } } func (Registration) Resources() []sdk.Resource { diff --git a/website/docs/d/elastic_san.html.markdown b/website/docs/d/elastic_san.html.markdown new file mode 100644 index 000000000000..fdee1228967b --- /dev/null +++ b/website/docs/d/elastic_san.html.markdown @@ -0,0 +1,74 @@ +--- +subcategory: "Elastic SAN" +layout: "azurerm" +page_title: "Azure Resource Manager: Data Source: azurerm_elastic_san" +description: |- + Gets information about an existing Elastic SAN. +--- + +# Data Source: azurerm_elastic_san + +Use this data source to access information about an existing Elastic SAN. + +## Example Usage + +```hcl +data "azurerm_elastic_san" "example" { + name = "existing" + resource_group_name = "existing" +} + +output "id" { + value = data.azurerm_elastic_san.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of this Elastic SAN. + +* `resource_group_name` - (Required) The name of the Resource Group where the Elastic SAN exists. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Elastic SAN. + +* `base_size_in_tib` - The base size of the Elastic SAN resource in TiB. + +* `extended_size_in_tib` - The base size of the Elastic SAN resource in TiB. + +* `location` - The Azure Region where the Elastic SAN exists. + +* `sku` - A `sku` block as defined below. + +* `tags` - A mapping of tags assigned to the Elastic SAN. + +* `total_iops` - Total Provisioned IOps of the Elastic SAN resource. + +* `total_mbps` - Total Provisioned MBps Elastic SAN resource. + +* `total_size_in_tib` - Total size of the Elastic SAN resource in TB. + +* `total_volume_size_in_gib` - Total size of the provisioned Volumes in GiB. + +* `volume_group_count` - Total number of volume groups in this Elastic SAN resource. + +* `zones` - Logical zone for the Elastic SAN resource. + +--- + +A `sku` block exports the following: + +* `name` - The SKU name. + +* `tier` - The SKU tier. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Elastic SAN.