From f92eac91d79e57732eeb29d32e88921022be4689 Mon Sep 17 00:00:00 2001 From: teowa <104055472+teowa@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:13:11 +0000 Subject: [PATCH 1/3] new data source azurerm_arc_resource_bridge_appliance --- ...c_resource_bridge_appliance_data_source.go | 121 ++++++++++++++++++ ...ource_bridge_appliance_data_source_test.go | 43 +++++++ ...resource_bridge_appliance_resource_test.go | 7 +- .../arcresourcebridge/registration.go | 4 +- ...rc_resource_bridge_appliance.html.markdown | 66 ++++++++++ ...rc_resource_bridge_appliance.html.markdown | 9 ++ 6 files changed, 245 insertions(+), 5 deletions(-) create mode 100644 internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go create mode 100644 internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source_test.go create mode 100644 website/docs/d/arc_resource_bridge_appliance.html.markdown diff --git a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go new file mode 100644 index 000000000000..929ec4fdd896 --- /dev/null +++ b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go @@ -0,0 +1,121 @@ +package arcresourcebridge + +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/identity" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/resourceconnector/2022-10-27/appliances" + "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" +) + +type ArcResourceBridgeApplianceDataSource struct{} + +var _ sdk.DataSource = ArcResourceBridgeApplianceDataSource{} + +func (r ArcResourceBridgeApplianceDataSource) ResourceType() string { + return "azurerm_arc_resource_bridge_appliance" +} + +func (r ArcResourceBridgeApplianceDataSource) ModelObject() interface{} { + return &ApplianceModel{} +} + +func (r ArcResourceBridgeApplianceDataSource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 260), + validation.StringMatch(regexp.MustCompile(`[^+#%&'?/,%\\]+$`), "any of '+', '#', '%', '&', ''', '?', '/', ',', '%', '&', '\\', are not allowed"), + ), + }, + + "resource_group_name": commonschema.ResourceGroupNameForDataSource(), + } +} + +func (r ArcResourceBridgeApplianceDataSource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "location": commonschema.LocationComputed(), + + "distro": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "identity": commonschema.SystemAssignedIdentityComputed(), + + "infrastructure_provider": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "public_key_base64": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "tags": commonschema.TagsDataSource(), + } +} + +func (r ArcResourceBridgeApplianceDataSource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.ArcResourceBridge.AppliancesClient + subscriptionId := metadata.Client.Account.SubscriptionId + + var model ApplianceModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + id := appliances.NewApplianceID(subscriptionId, model.ResourceGroupName, model.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) + } + + state := ApplianceModel{ + Name: model.Name, + ResourceGroupName: model.ResourceGroupName, + } + + if model := resp.Model; model != nil { + state.Location = location.Normalize(model.Location) + state.Identity = identity.FlattenSystemAssignedToModel(model.Identity) + state.Tags = tags.Flatten(model.Tags) + + if props := model.Properties; props != nil { + state.Distro = pointer.From(props.Distro) + state.PublicKeyBase64 = pointer.From(props.PublicKey) + + if infraConfig := props.InfrastructureConfig; infraConfig != nil { + state.Provider = pointer.From(infraConfig.Provider) + } + } + } + + metadata.SetID(id) + + return metadata.Encode(&state) + }, + } +} diff --git a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source_test.go b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source_test.go new file mode 100644 index 000000000000..a9cfbcc07ca5 --- /dev/null +++ b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source_test.go @@ -0,0 +1,43 @@ +package arcresourcebridge_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type ArcResourceBridgeApplianceDataSource struct{} + +func TestAccArcResourceBridgeApplianceDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_arc_resource_bridge_appliance", "test") + d := ArcResourceBridgeApplianceDataSource{} + + data.DataSourceTestInSequence(t, []acceptance.TestStep{ + { + Config: d.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("location").IsNotEmpty(), + check.That(data.ResourceName).Key("distro").IsNotEmpty(), + check.That(data.ResourceName).Key("infrastructure_provider").IsNotEmpty(), + check.That(data.ResourceName).Key("public_key_base64").IsNotEmpty(), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned"), + check.That(data.ResourceName).Key("identity.0.tenant_id").IsNotEmpty(), + check.That(data.ResourceName).Key("identity.0.principal_id").IsNotEmpty(), + check.That(data.ResourceName).Key("tags.%").HasValue("1"), + ), + }, + }) +} + +func (d ArcResourceBridgeApplianceDataSource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +data "azurerm_arc_resource_bridge_appliance" "test" { + name = azurerm_arc_resource_bridge_appliance.test.name + resource_group_name = azurerm_arc_resource_bridge_appliance.test.resource_group_name +} +`, ArcResourceBridgeApplianceResource{}.complete(data)) +} diff --git a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_resource_test.go b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_resource_test.go index 7ae5f11c9568..9fe5f4b9350a 100644 --- a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_resource_test.go +++ b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_resource_test.go @@ -72,7 +72,7 @@ func TestAccArcResourceBridgeAppliance_complete(t *testing.T) { data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.complete(data, r.generatePublicKey()), + Config: r.complete(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -103,7 +103,6 @@ func (r ArcResourceBridgeApplianceResource) Exists(ctx context.Context, clients client := clients.ArcResourceBridge.AppliancesClient resp, err := client.Get(ctx, *id) - if err != nil { return nil, fmt.Errorf("retrieving %q: %+v", *id, err) } @@ -150,7 +149,7 @@ resource "azurerm_arc_resource_bridge_appliance" "test" { `, r.template(data), data.RandomInteger) } -func (r ArcResourceBridgeApplianceResource) complete(data acceptance.TestData, publicKey string) string { +func (r ArcResourceBridgeApplianceResource) complete(data acceptance.TestData) string { return fmt.Sprintf(` %s @@ -169,7 +168,7 @@ resource "azurerm_arc_resource_bridge_appliance" "test" { "hello" = "world" } } -`, r.template(data), data.RandomInteger, publicKey) +`, r.template(data), data.RandomInteger, r.generatePublicKey()) } func (r ArcResourceBridgeApplianceResource) requiresImport(data acceptance.TestData) string { diff --git a/internal/services/arcresourcebridge/registration.go b/internal/services/arcresourcebridge/registration.go index 4d9c2627a4a7..3643374ff447 100644 --- a/internal/services/arcresourcebridge/registration.go +++ b/internal/services/arcresourcebridge/registration.go @@ -20,7 +20,9 @@ func (r Registration) Name() string { } func (r Registration) DataSources() []sdk.DataSource { - return []sdk.DataSource{} + return []sdk.DataSource{ + ArcResourceBridgeApplianceDataSource{}, + } } func (r Registration) Resources() []sdk.Resource { diff --git a/website/docs/d/arc_resource_bridge_appliance.html.markdown b/website/docs/d/arc_resource_bridge_appliance.html.markdown new file mode 100644 index 000000000000..aacd883496b7 --- /dev/null +++ b/website/docs/d/arc_resource_bridge_appliance.html.markdown @@ -0,0 +1,66 @@ +--- +subcategory: "Arc Resource Bridge" +layout: "azurerm" +page_title: "Azure Resource Manager: Data Source: azurerm_arc_resource_bridge_appliance" +description: |- + Gets information about an existing Arc Resource Bridge Appliance. +--- + +# Data Source: azurerm_arc_resource_bridge_appliance + +Use this data source to access information about an existing Arc Resource Bridge Appliance. + +## Example Usage + +```hcl +data "azurerm_arc_resource_bridge_appliance" "example" { + name = "existing" + resource_group_name = "existing" +} + +output "id" { + value = data.azurerm_arc_resource_bridge_appliance.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of this Arc Resource Bridge Appliance. + +* `resource_group_name` - (Required) The name of the Resource Group where the Arc Resource Bridge Appliance exists. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Arc Resource Bridge Appliance. + +* `distro` - Fabric/Infrastructure for this Arc Resource Bridge Appliance. + +* `identity` - An `identity` block as defined below. + +* `infrastructure_provider` - The infrastructure provider about the connected Arc Resource Bridge Appliance. + +* `location` - The Azure Region where the Arc Resource Bridge Appliance exists. + +* `public_key_base64` - RSA public key in PKCS1 format encoded in base64. + +* `tags` - A mapping of tags assigned to the Arc Resource Bridge Appliance. + +--- + +An `identity` block exports the following: + +* `principal_id` - The Principal ID associated with this Managed Service Identity. + +* `tenant_id` - The Tenant ID associated with this Managed Service Identity. + +* `type` - The type of this Managed Service Identity. + +## 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 Arc Resource Bridge Appliance. diff --git a/website/docs/r/arc_resource_bridge_appliance.html.markdown b/website/docs/r/arc_resource_bridge_appliance.html.markdown index 318624897b4b..dd7678717d73 100644 --- a/website/docs/r/arc_resource_bridge_appliance.html.markdown +++ b/website/docs/r/arc_resource_bridge_appliance.html.markdown @@ -68,6 +68,15 @@ In addition to the Arguments listed above - the following Attributes are exporte * `id` - The ID of the Arc Resource Bridge Appliance. +* `identity` - A `identity` block as defined below. + +--- +An `identity` block exports the following: + +* `principal_id` - The Principal ID associated with this Managed Service Identity. + +* `tenant_id` - The Tenant ID associated with this Managed Service Identity. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: From 712f1115558cdb0a38efad65f7ffa49407717fdb Mon Sep 17 00:00:00 2001 From: teowa <104055472+teowa@users.noreply.github.com> Date: Thu, 25 Apr 2024 08:39:22 +0000 Subject: [PATCH 2/3] split data source model --- ...arc_resource_bridge_appliance_data_source.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go index 929ec4fdd896..d4d5a75431f2 100644 --- a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go +++ b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go @@ -22,12 +22,23 @@ type ArcResourceBridgeApplianceDataSource struct{} var _ sdk.DataSource = ArcResourceBridgeApplianceDataSource{} +type ApplianceDataSourceModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + Distro appliances.Distro `tfschema:"distro"` + Identity []identity.ModelSystemAssigned `tfschema:"identity"` + Provider appliances.Provider `tfschema:"infrastructure_provider"` + PublicKeyBase64 string `tfschema:"public_key_base64"` + Tags map[string]interface{} `tfschema:"tags"` +} + func (r ArcResourceBridgeApplianceDataSource) ResourceType() string { return "azurerm_arc_resource_bridge_appliance" } func (r ArcResourceBridgeApplianceDataSource) ModelObject() interface{} { - return &ApplianceModel{} + return &ApplianceDataSourceModel{} } func (r ArcResourceBridgeApplianceDataSource) Arguments() map[string]*pluginsdk.Schema { @@ -77,7 +88,7 @@ func (r ArcResourceBridgeApplianceDataSource) Read() sdk.ResourceFunc { client := metadata.Client.ArcResourceBridge.AppliancesClient subscriptionId := metadata.Client.Account.SubscriptionId - var model ApplianceModel + var model ApplianceDataSourceModel if err := metadata.Decode(&model); err != nil { return fmt.Errorf("decoding: %+v", err) } @@ -93,7 +104,7 @@ func (r ArcResourceBridgeApplianceDataSource) Read() sdk.ResourceFunc { return fmt.Errorf("retrieving %s: %+v", id, err) } - state := ApplianceModel{ + state := ApplianceDataSourceModel{ Name: model.Name, ResourceGroupName: model.ResourceGroupName, } From 44d7a863133ce93743b0f4d2913b2c287ff1516e Mon Sep 17 00:00:00 2001 From: teowa <104055472+teowa@users.noreply.github.com> Date: Fri, 26 Apr 2024 08:13:24 +0000 Subject: [PATCH 3/3] fix --- .../arc_resource_bridge_appliance_data_source.go | 11 +++-------- .../r/arc_resource_bridge_appliance.html.markdown | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go index d4d5a75431f2..c227d85709c7 100644 --- a/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go +++ b/internal/services/arcresourcebridge/arc_resource_bridge_appliance_data_source.go @@ -88,12 +88,12 @@ func (r ArcResourceBridgeApplianceDataSource) Read() sdk.ResourceFunc { client := metadata.Client.ArcResourceBridge.AppliancesClient subscriptionId := metadata.Client.Account.SubscriptionId - var model ApplianceDataSourceModel - if err := metadata.Decode(&model); err != nil { + var state ApplianceDataSourceModel + if err := metadata.Decode(&state); err != nil { return fmt.Errorf("decoding: %+v", err) } - id := appliances.NewApplianceID(subscriptionId, model.ResourceGroupName, model.Name) + id := appliances.NewApplianceID(subscriptionId, state.ResourceGroupName, state.Name) resp, err := client.Get(ctx, id) if err != nil { @@ -104,11 +104,6 @@ func (r ArcResourceBridgeApplianceDataSource) Read() sdk.ResourceFunc { return fmt.Errorf("retrieving %s: %+v", id, err) } - state := ApplianceDataSourceModel{ - Name: model.Name, - ResourceGroupName: model.ResourceGroupName, - } - if model := resp.Model; model != nil { state.Location = location.Normalize(model.Location) state.Identity = identity.FlattenSystemAssignedToModel(model.Identity) diff --git a/website/docs/r/arc_resource_bridge_appliance.html.markdown b/website/docs/r/arc_resource_bridge_appliance.html.markdown index dd7678717d73..6a879a3be8be 100644 --- a/website/docs/r/arc_resource_bridge_appliance.html.markdown +++ b/website/docs/r/arc_resource_bridge_appliance.html.markdown @@ -68,7 +68,7 @@ In addition to the Arguments listed above - the following Attributes are exporte * `id` - The ID of the Arc Resource Bridge Appliance. -* `identity` - A `identity` block as defined below. +* `identity` - An `identity` block as defined below. --- An `identity` block exports the following: