Skip to content

Commit

Permalink
Fix missing power_state attribute value for `azurerm_virtual_machin…
Browse files Browse the repository at this point in the history
…e` and `azurerm_virtual_machine_scale_set` data sources (#26991)

* instanceView working on VM and VMSS

* Add power_state test

* fix linting

* switch to pointer and nil check
  • Loading branch information
ned1313 authored Aug 16, 2024
1 parent 09bc334 commit 916eec2
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 19 deletions.
5 changes: 4 additions & 1 deletion internal/services/compute/virtual_machine_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"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"
Expand Down Expand Up @@ -85,7 +86,9 @@ func dataSourceVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{}) e

id := virtualmachines.NewVirtualMachineID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string))

resp, err := client.Get(ctx, id, virtualmachines.DefaultGetOperationOptions())
options := virtualmachines.DefaultGetOperationOptions()
options.Expand = pointer.To(virtualmachines.InstanceViewTypesInstanceView)
resp, err := client.Get(ctx, id, options)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
Expand Down
2 changes: 2 additions & 0 deletions internal/services/compute/virtual_machine_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestAccDataSourceAzureRMVirtualMachine_basicLinux(t *testing.T) {
check.That(data.ResourceName).Key("identity.0.principal_id").Exists(),
check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(),
check.That(data.ResourceName).Key("private_ip_address").HasValue("10.0.2.4"),
check.That(data.ResourceName).Key("power_state").HasValue("running"),
),
},
})
Expand All @@ -44,6 +45,7 @@ func TestAccDataSourceAzureRMVirtualMachine_basicWindows(t *testing.T) {
check.That(data.ResourceName).Key("identity.0.principal_id").Exists(),
check.That(data.ResourceName).Key("identity.0.tenant_id").Exists(),
check.That(data.ResourceName).Key("private_ip_address").HasValue("10.0.2.4"),
check.That(data.ResourceName).Key("power_state").HasValue("running"),
),
},
})
Expand Down
81 changes: 63 additions & 18 deletions internal/services/compute/virtual_machine_scale_set_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,32 @@ func dataSourceVirtualMachineScaleSetRead(d *pluginsdk.ResourceData, meta interf

instances := make([]interface{}, 0)
virtualMachineScaleSetId := virtualmachinescalesetvms.NewVirtualMachineScaleSetID(subscriptionId, id.ResourceGroupName, id.VirtualMachineScaleSetName)
result, err := instancesClient.ListComplete(ctx, virtualMachineScaleSetId, virtualmachinescalesetvms.DefaultListOperationOptions())

// If the VMSS is in Uniform Orchestration Mode, we can use instanceView for the VMSS instances
// Flexible VMSS instances cannot use instanceView from the VMSS API
// Instead we need to use the VM API for instanceView
optionsVMSS := virtualmachinescalesetvms.DefaultListOperationOptions()
optionsVM := virtualmachines.DefaultGetOperationOptions()
var orchestrationMode string
if props := resp.Model.Properties; props != nil {
if *props.OrchestrationMode == virtualmachinescalesets.OrchestrationModeUniform {
expandStr := "instanceView"
optionsVMSS.Expand = &expandStr
orchestrationMode = "Uniform"
}
if *props.OrchestrationMode == virtualmachinescalesets.OrchestrationModeFlexible {
optionsVM.Expand = pointer.To(virtualmachines.InstanceViewTypesInstanceView)
orchestrationMode = "Flexible"
}
}

result, err := instancesClient.ListComplete(ctx, virtualMachineScaleSetId, optionsVMSS)
if err != nil {
return fmt.Errorf("listing VM Instances for %q: %+v", id, err)
}

var connInfo *connectionInfo
var vmModel *virtualmachines.VirtualMachine
for _, item := range result.Items {
if item.InstanceId != nil {
vmId := networkinterfaces.NewVirtualMachineID(subscriptionId, id.ResourceGroupName, id.VirtualMachineScaleSetName, *item.InstanceId)
Expand All @@ -187,20 +207,21 @@ func dataSourceVirtualMachineScaleSetRead(d *pluginsdk.ResourceData, meta interf

// Network Interfaces of VM in Flexible VMSS are accessed from single VM
virtualMachineId := virtualmachines.NewVirtualMachineID(subscriptionId, id.ResourceGroupName, *item.InstanceId)
vm, err := virtualMachinesClient.Get(ctx, virtualMachineId, virtualmachines.DefaultGetOperationOptions())
vm, err := virtualMachinesClient.Get(ctx, virtualMachineId, optionsVM)
if err != nil {
return fmt.Errorf("retrieving VM Instance %q for %q: %+v", *item.InstanceId, id, err)
}
connInfoRaw := retrieveConnectionInformation(ctx, networkInterfacesClient, publicIPAddressesClient, vm.Model.Properties)
connInfo = &connInfoRaw
vmModel = vm.Model
} else {
connInfo, err = getVirtualMachineScaleSetVMConnectionInfo(ctx, nics.Items, id.ResourceGroupName, id.VirtualMachineScaleSetName, *item.InstanceId, vmssPublicIpAddressesClient)
if err != nil {
return err
}
}

flattenedInstances := flattenVirtualMachineScaleSetVM(item, connInfo)
flattenedInstances := flattenVirtualMachineScaleSetVM(item, connInfo, vmModel, orchestrationMode)
instances = append(instances, flattenedInstances)
}
}
Expand Down Expand Up @@ -275,29 +296,53 @@ func getVirtualMachineScaleSetVMConnectionInfo(ctx context.Context, networkInter
}, nil
}

func flattenVirtualMachineScaleSetVM(input virtualmachinescalesetvms.VirtualMachineScaleSetVM, connectionInfo *connectionInfo) map[string]interface{} {
func flattenVirtualMachineScaleSetVM(input virtualmachinescalesetvms.VirtualMachineScaleSetVM, connectionInfo *connectionInfo, vm *virtualmachines.VirtualMachine, mode string) map[string]interface{} {
output := make(map[string]interface{})
output["name"] = *input.Name
output["instance_id"] = *input.InstanceId

if props := input.Properties; props != nil {
if props.LatestModelApplied != nil {
output["latest_model_applied"] = *props.LatestModelApplied
}
if mode == "Flexible" && vm != nil {
if props := vm.Properties; props != nil {
if props.VMId != nil {
output["virtual_machine_id"] = *props.VMId
}

if props.VMId != nil {
output["virtual_machine_id"] = *props.VMId
}
if profile := props.OsProfile; profile != nil && profile.ComputerName != nil {
output["computer_name"] = *profile.ComputerName
}

if profile := props.OsProfile; profile != nil && profile.ComputerName != nil {
output["computer_name"] = *profile.ComputerName
if instance := props.InstanceView; instance != nil {
if statuses := instance.Statuses; statuses != nil {
for _, status := range *statuses {
if status.Code != nil && strings.HasPrefix(strings.ToLower(*status.Code), "powerstate/") {
output["power_state"] = strings.SplitN(*status.Code, "/", 2)[1]
}
}
}
}
}
}

if mode == "Uniform" {
if props := input.Properties; props != nil {
if props.LatestModelApplied != nil {
output["latest_model_applied"] = *props.LatestModelApplied
}

if instance := props.InstanceView; instance != nil {
if statuses := instance.Statuses; statuses != nil {
for _, status := range *statuses {
if status.Code != nil && strings.HasPrefix(strings.ToLower(*status.Code), "powerstate/") {
output["power_state"] = strings.SplitN(*status.Code, "/", 2)[1]
if props.VMId != nil {
output["virtual_machine_id"] = *props.VMId
}

if profile := props.OsProfile; profile != nil && profile.ComputerName != nil {
output["computer_name"] = *profile.ComputerName
}

if instance := props.InstanceView; instance != nil {
if statuses := instance.Statuses; statuses != nil {
for _, status := range *statuses {
if status.Code != nil && strings.HasPrefix(strings.ToLower(*status.Code), "powerstate/") {
output["power_state"] = strings.SplitN(*status.Code, "/", 2)[1]
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestAccDataSourceVirtualMachineScaleSet_basicLinux(t *testing.T) {
check.That(data.ResourceName).Key("instances.#").HasValue("1"),
check.That(data.ResourceName).Key("instances.0.instance_id").HasValue("0"),
check.That(data.ResourceName).Key("instances.0.private_ip_address").HasValue("10.0.2.4"),
check.That(data.ResourceName).Key("instances.0.power_state").HasValue("running"),
),
},
})
Expand Down

0 comments on commit 916eec2

Please sign in to comment.