Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Data Source: azurerm_system_center_virtual_machine_manager_inventory_items #25110

2 changes: 1 addition & 1 deletion .github/labeler-issue-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ service/synapse:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_synapse_((.|\n)*)###'

service/systemcentervirtualmachinemanager:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_system_center_virtual_machine_manager_server((.|\n)*)###'
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_system_center_virtual_machine_manager_((.|\n)*)###'

service/traffic-manager:
- '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_traffic_manager_((.|\n)*)###'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ func (r Registration) WebsiteCategories() []string {
}

func (r Registration) DataSources() []sdk.DataSource {
return []sdk.DataSource{}
return []sdk.DataSource{
SystemCenterVirtualMachineManagerInventoryItemsDataSource{},
}
}

func (r Registration) Resources() []sdk.Resource {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package systemcentervirtualmachinemanager

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-sdk/resource-manager/systemcentervirtualmachinemanager/2023-10-07/inventoryitems"
"github.com/hashicorp/go-azure-sdk/resource-manager/systemcentervirtualmachinemanager/2023-10-07/vmmservers"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

type SystemCenterVirtualMachineManagerInventoryItemsDataSource struct{}

var _ sdk.DataSource = SystemCenterVirtualMachineManagerInventoryItemsDataSource{}

type SystemCenterVirtualMachineManagerInventoryItemsDataSourceModel struct {
SystemCenterVirtualMachineManagerServerId string `tfschema:"system_center_virtual_machine_manager_server_id"`
InventoryItems []InventoryItem `tfschema:"inventory_items"`
}

type InventoryItem struct {
id string `tfschema:"id"`
name string `tfschema:"name"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neither of these two fields is exported, so would need to be to be set into the state

Copy link
Contributor Author

@neil-yechenwei neil-yechenwei Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InventoryType string `tfschema:"inventory_type"`
Uuid string `tfschema:"uuid"`
}

func (l SystemCenterVirtualMachineManagerInventoryItemsDataSource) ResourceType() string {
return "azurerm_system_center_virtual_machine_manager_inventory_items"
}

func (l SystemCenterVirtualMachineManagerInventoryItemsDataSource) ModelObject() interface{} {
return &SystemCenterVirtualMachineManagerInventoryItemsDataSourceModel{}
}

func (l SystemCenterVirtualMachineManagerInventoryItemsDataSource) Arguments() map[string]*schema.Schema {
return map[string]*pluginsdk.Schema{
"system_center_virtual_machine_manager_server_id": commonschema.ResourceIDReferenceRequired(&vmmservers.VMmServerId{}),
}
}

func (l SystemCenterVirtualMachineManagerInventoryItemsDataSource) Attributes() map[string]*schema.Schema {
return map[string]*pluginsdk.Schema{
"inventory_items": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"name": {
Type: pluginsdk.TypeString,
Computed: true,
},

"inventory_type": {
Type: pluginsdk.TypeString,
Computed: true,
},

"uuid": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
},
},
}
}

func (l SystemCenterVirtualMachineManagerInventoryItemsDataSource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.SystemCenterVirtualMachineManager.InventoryItems

var state SystemCenterVirtualMachineManagerInventoryItemsDataSourceModel
if err := metadata.Decode(&state); err != nil {
return err
}

scvmmServerId, err := inventoryitems.ParseVMmServerIDInsensitively(state.SystemCenterVirtualMachineManagerServerId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason we're parsing this insensitively?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tom suggests to use insensitively. See more details from #23628 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is coming from a user specified value rather than an API returned value - so should be case-sensitive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

if err != nil {
return err
}

id := fmt.Sprintf("%s/inventoryItems", scvmmServerId.ID())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we constructing this ID with inventoryitems.NewInventoryItemID()?

Copy link
Contributor Author

@neil-yechenwei neil-yechenwei Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason 1: inventoryitems.NewInventoryItemID() points to the dependent Inventory Item resource and service team expects us to not expose it to users.

Reason 2: Setting inventoryitems.NewInventoryItemID() requires the specified Inventory Item Id but this data source is used to expose a list of Inventory Items. So I assume that we couldn't set it with any Inventory Item Id in the list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be defining Terraform specific Resource IDs where they aren't absolutely necessary - this is a great example of where we should be using the SCVMM Server ID rather than creating something random - can we update this as @stephybun mentions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use SCVMM Server ID.


resp, err := client.ListByVMMServer(ctx, *scvmmServerId)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("reading %s: %+v", id, err)
}

if model := resp.Model; model != nil {
inventoryItems := flattenInventoryItems(model)
if len(inventoryItems) == 0 {
return fmt.Errorf("no inventory items were found for %s", scvmmServerId)
}
state.InventoryItems = inventoryItems
}

metadata.ResourceData.SetId(id)

return metadata.Encode(&state)
},
}
}

func flattenInventoryItems(input *[]inventoryitems.InventoryItem) []InventoryItem {
results := make([]InventoryItem, 0)
if input == nil {
return results
}

for _, item := range *input {
inventoryItem := InventoryItem{
id: pointer.From(item.Id),
}

if props := item.Properties; props != nil {
if v, ok := props.(inventoryitems.CloudInventoryItem); ok {
inventoryItem.name = pointer.From(v.InventoryItemName)
inventoryItem.Uuid = pointer.From(v.Uuid)
inventoryItem.InventoryType = string(inventoryitems.InventoryTypeCloud)
} else if v, ok := props.(inventoryitems.VirtualMachineInventoryItem); ok {
inventoryItem.name = pointer.From(v.InventoryItemName)
inventoryItem.Uuid = pointer.From(v.Uuid)
inventoryItem.InventoryType = string(inventoryitems.InventoryTypeVirtualMachine)
} else if v, ok := props.(inventoryitems.VirtualMachineTemplateInventoryItem); ok {
inventoryItem.name = pointer.From(v.InventoryItemName)
inventoryItem.Uuid = pointer.From(v.Uuid)
inventoryItem.InventoryType = string(inventoryitems.InventoryTypeVirtualMachineTemplate)
} else if v, ok := props.(inventoryitems.VirtualNetworkInventoryItem); ok {
inventoryItem.name = pointer.From(v.InventoryItemName)
inventoryItem.Uuid = pointer.From(v.Uuid)
inventoryItem.InventoryType = string(inventoryitems.InventoryTypeVirtualNetwork)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the number of items that could be returned here, this isn't going to be particularly usable.

Perhaps it'd be sensible to add a Name and Type filter to this resource, to obtain an Item rather than a list of Items, to make this more useful?

Copy link
Contributor Author

@neil-yechenwei neil-yechenwei Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Inventory Items are automatically created by the service while creating System Center Virtual Machine Manager. Service team confirmed that the end users can't create the Inventory Items. So the users don't know the "Name" of the Inventory Item when getting an specific Inventory Item. Hence, I made this data source to get a list of Inventory Items.

But seems it makes sense to add a filter "Inventory Type". So I updated PR to add a filter "Inventory Type" to get a list of the inventory items by the "Inventory Type".

}

results = append(results, inventoryItem)
}

return results
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package systemcentervirtualmachinemanager_test

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
)

type SystemCenterVirtualMachineManagerInventoryItemsDataSource struct{}

func TestAccDataSourceSystemCenterVirtualMachineManagerInventoryItems_basic(t *testing.T) {
if os.Getenv("ARM_TEST_CUSTOM_LOCATION_ID") == "" || os.Getenv("ARM_TEST_FQDN") == "" || os.Getenv("ARM_TEST_USERNAME") == "" || os.Getenv("ARM_TEST_PASSWORD") == "" {
t.Skip("Skipping as one of `ARM_TEST_CUSTOM_LOCATION_ID`, `ARM_TEST_FQDN`, `ARM_TEST_USERNAME`, `ARM_TEST_PASSWORD` was not specified")
}

data := acceptance.BuildTestData(t, "data.azurerm_system_center_virtual_machine_manager_inventory_items", "test")
r := SystemCenterVirtualMachineManagerInventoryItemsDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: r.basic(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("inventory_items.#").Exists(),
),
},
})
}

func (d SystemCenterVirtualMachineManagerInventoryItemsDataSource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

// Service team confirmed that waiting to sync Inventory Items in System Center Virtual Machine Manager Server is expected behaviour since the backend operator creates CRD (Custom Resource Definitions) for all the existing resources from onPrem and create InventoryItem resources which takes some time depending upon the number of resources after PUT System Center Virtual Machine Manager Server operation
resource "time_sleep" "wait_1_minute" {
depends_on = [azurerm_system_center_virtual_machine_manager_server.test]

create_duration = "1m"
}

data "azurerm_system_center_virtual_machine_manager_inventory_items" "test" {
system_center_virtual_machine_manager_server_id = azurerm_system_center_virtual_machine_manager_server.test.id

depends_on = [time_sleep.wait_1_minute]
}
`, SystemCenterVirtualMachineManagerServerResource{}.basic(data))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
subcategory: "System Center Virtual Machine Manager"
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_system_center_virtual_machine_manager_inventory_items"
description: |-
Gets information about existing System Center Virtual Machine Manager Inventory Items.
---

# Data Source: azurerm_system_center_virtual_machine_manager_inventory_items

Use this data source to access information about existing System Center Virtual Machine Manager Inventory Items.

## Example Usage

```hcl
data "azurerm_system_center_virtual_machine_manager_inventory_items" "example" {
system_center_virtual_machine_manager_server_id = azurerm_system_center_virtual_machine_manager_server.example.id
}
```

## Argument Reference

* `system_center_virtual_machine_manager_server_id` - The ID of the System Center Virtual Machine Manager Server.

## Attributes Reference

* `id` - The ID of the System Center Virtual Machine Manager Inventory Items.

* `inventory_items` - One or more `inventory_items` blocks as defined below.

---

A `inventory_items` block exports the following:

* `id` - The ID of the System Center Virtual Machine Manager Inventory Item.

* `name` - The name of the System Center Virtual Machine Manager Inventory Item.

* `inventory_type` - The inventory type of the System Center Virtual Machine Manager Inventory Item.

* `uuid` - The UUID of the System Center Virtual Machine Manager Inventory Item that is assigned by System Center Virtual Machine Manager.

## 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 System Center Virtual Machine Manager Inventory Items.
Loading