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 Datasource: azurerm_orchestrated_virtual_machine_scale_set #21050

Merged
merged 6 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions internal/services/compute/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ func flattenSubResourcesToIDs(input *[]compute.SubResource) []interface{} {
return ids
}

func flattenSubResourcesToStringIDs(input *[]compute.SubResource) []string {
ids := make([]string, 0)
if input == nil {
return ids
}

for _, v := range *input {
if v.ID == nil {
continue
}

ids = append(ids, *v.ID)
}

return ids
}

func sortSharedImageVersions(values []compute.GalleryImageVersion) ([]compute.GalleryImageVersion, []error) {
errors := make([]error, 0)
sort.Slice(values, func(i, j int) bool {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
package compute

import (
"context"
"fmt"
"time"

"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/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/parse"
computeValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/compute/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
"github.com/tombuildsstuff/kermit/sdk/compute/2022-08-01/compute"
)

type OrchestratedVirtualMachineScaleSetDataSource struct{}

var _ sdk.DataSource = OrchestratedVirtualMachineScaleSetDataSource{}

type OrchestratedVirtualMachineScaleSetDataSourceModel struct {
Name string `tfschema:"name"`
ResourceGroup string `tfschema:"resource_group_name"`
Location string `tfschema:"location"`
NetworkInterface []VirtualMachineScaleSetNetworkInterface `tfschema:"network_interface"`
Identity []identity.ModelUserAssigned `tfschema:"identity"`
}

type VirtualMachineScaleSetNetworkInterface struct {
Name string `tfschema:"name"`
IPConfiguration []VirtualMachineScaleSetNetworkInterfaceIPConfiguration
DNSServers []string `tfschema:"dns_servers"`
AcceleratedNetworkingEnabled bool `tfschema:"accelerated_networking_enabled"`
IPForwardingEnabled bool `tfschema:"ip_forwarding_enabled"`
NetworkSecurityGroupId string `tfschema:"network_security_group_id"`
Primary bool `tfschema:"primary"`
}

type VirtualMachineScaleSetNetworkInterfaceIPConfiguration struct {
Name string `tfschema:"name"`
ApplicationGatewayBackendAddressPoolIds []string `tfschema:"application_gateway_backend_address_pool_ids"`
ApplicationSecurityGroupIds []string `tfschema:"application_security_group_ids"`
LoadBalancerBackendAddressPoolIds []string `tfschema:"load_balancer_backend_address_pool_ids"`
Primary bool `tfschema:"primary"`
PublicIPAddress VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddress `tfschema:"public_ip_address"`
SubnetId string `tfschema:"subnet_id"`
Version string `tfschema:"version"`
}

type VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddress struct {
Name string `tfschema:"name"`
DomainNameLabel string `tfschema:"domain_name_label"`
IdleTimeoutInMinutes int `tfschema:"idle_timeout_in_minutes"`
IPTag []VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddressIPTag `tfschema:"ip_tag"`
PublicIpPrefixId string `tfschema:"public_ip_prefix_id"`
SkuName string `tfschema:"sku_name"`
Version string `tfschema:"version"`
}

type VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddressIPTag struct {
Tag string `tfschema:"tag"`
Type string `tfschema:"type"`
}

func (r OrchestratedVirtualMachineScaleSetDataSource) ModelObject() interface{} {
return &OrchestratedVirtualMachineScaleSetDataSourceModel{}
}

func (r OrchestratedVirtualMachineScaleSetDataSource) ResourceType() string {
return "azurerm_orchestrated_virtual_machine_scale_set"
}

func (r OrchestratedVirtualMachineScaleSetDataSource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: computeValidate.VirtualMachineName,
},

"resource_group_name": commonschema.ResourceGroupNameForDataSource(),
}
}

func (r OrchestratedVirtualMachineScaleSetDataSource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"location": commonschema.LocationComputed(),

"network_interfaces": OrchestratedVirtualMachineScaleSetNetworkInterfaceSchema(),
}
}

func (r OrchestratedVirtualMachineScaleSetDataSource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Compute.VMScaleSetClient
subscriptionId := metadata.Client.Account.SubscriptionId

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

id := parse.NewVirtualMachineScaleSetID(subscriptionId, orchestratedVMSS.ResourceGroup, orchestratedVMSS.Name)

existing, err := client.Get(ctx, id.ResourceGroup, id.Name, compute.ExpandTypesForGetVMScaleSetsUserData)
if err != nil {
if utils.ResponseWasNotFound(existing.Response) {
return fmt.Errorf("%s not found", id)
}
return fmt.Errorf("retrieving %s: %+v", id, err)
}

orchestratedVMSS.Location = location.NormalizeNilable(existing.Location)

if profile := existing.VirtualMachineProfile; profile != nil {
if nwProfile := profile.NetworkProfile; nwProfile != nil {
orchestratedVMSS.NetworkInterface = flattenVirtualMachineScaleSetNetworkInterface(nwProfile.NetworkInterfaceConfigurations)
}
}

userIdentity, err := flattenOrchestratedVirtualMachineScaleSetIdentityToModel(existing.Identity)
if err != nil {
return err
}
orchestratedVMSS.Identity = userIdentity

metadata.SetID(id)

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

func flattenVirtualMachineScaleSetNetworkInterface(input *[]compute.VirtualMachineScaleSetNetworkConfiguration) []VirtualMachineScaleSetNetworkInterface {
if input == nil {
return []VirtualMachineScaleSetNetworkInterface{}
}

networkInterfaces := make([]VirtualMachineScaleSetNetworkInterface, 0)
for _, v := range *input {
var name, networkSecurityGroupId string
if v.Name != nil {
name = *v.Name
}
if v.NetworkSecurityGroup != nil && v.NetworkSecurityGroup.ID != nil {
networkSecurityGroupId = *v.NetworkSecurityGroup.ID
}
var acceleratedNetworkingEnabled, ipForwardingEnabled, primary bool
if v.EnableAcceleratedNetworking != nil {
acceleratedNetworkingEnabled = *v.EnableAcceleratedNetworking
}
if v.EnableIPForwarding != nil {
ipForwardingEnabled = *v.EnableIPForwarding
}
if v.Primary != nil {
primary = *v.Primary
}

var dnsServers []string
if settings := v.DNSSettings; settings != nil {
dnsServers = *v.DNSSettings.DNSServers
}

var ipConfigurations []interface{}
if v.IPConfigurations != nil {
for _, configRaw := range *v.IPConfigurations {
config := flattenVirtualMachineScaleSetIPConfiguration(configRaw)
ipConfigurations = append(ipConfigurations, config)
}
}
networkInterfaces = append(networkInterfaces, VirtualMachineScaleSetNetworkInterface{
Name: name,
NetworkSecurityGroupId: networkSecurityGroupId,
AcceleratedNetworkingEnabled: acceleratedNetworkingEnabled,
IPForwardingEnabled: ipForwardingEnabled,
Primary: primary,
DNSServers: dnsServers,
IPConfiguration: flattenOrchestratedVirtualMachineScaleSetNetworkInterfaceIPConfiguration(v.IPConfigurations),
})
}

return networkInterfaces
}

func flattenOrchestratedVirtualMachineScaleSetNetworkInterfaceIPConfiguration(input *[]compute.VirtualMachineScaleSetIPConfiguration) []VirtualMachineScaleSetNetworkInterfaceIPConfiguration {
if input == nil {
return []VirtualMachineScaleSetNetworkInterfaceIPConfiguration{}
}

ipConfigurations := make([]VirtualMachineScaleSetNetworkInterfaceIPConfiguration, 0)
for _, v := range *input {
var name, subnetId string
if v.Name != nil {
name = *v.Name
}
if v.Subnet != nil && v.Subnet.ID != nil {
subnetId = *v.Subnet.ID
}

var primary bool
if v.Primary != nil {
primary = *v.Primary
}

ipConfigurations = append(ipConfigurations, VirtualMachineScaleSetNetworkInterfaceIPConfiguration{
Name: name,
SubnetId: subnetId,
Primary: primary,
PublicIPAddress: flattenOrchestratedVirtualMachineScaleSetPublicIPAddress(v.PublicIPAddressConfiguration),
ApplicationGatewayBackendAddressPoolIds: flattenSubResourcesToStringIDs(v.ApplicationGatewayBackendAddressPools),
ApplicationSecurityGroupIds: flattenSubResourcesToStringIDs(v.ApplicationSecurityGroups),
LoadBalancerBackendAddressPoolIds: flattenSubResourcesToStringIDs(v.LoadBalancerBackendAddressPools),
})
}

return ipConfigurations
}

func flattenOrchestratedVirtualMachineScaleSetPublicIPAddress(input *compute.VirtualMachineScaleSetPublicIPAddressConfiguration) VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddress {
if input == nil {
return VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddress{}
}

ipTags := make([]VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddressIPTag, 0)
if input.IPTags != nil {
for _, rawTag := range *input.IPTags {
var tag, tagType string

if rawTag.IPTagType != nil {
tagType = *rawTag.IPTagType
}

if rawTag.Tag != nil {
tag = *rawTag.Tag
}

ipTags = append(ipTags, VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddressIPTag{
Tag: tag,
Type: tagType,
})
}
}

var domainNameLabel, name, publicIPPrefixId, version string
if input.DNSSettings != nil && input.DNSSettings.DomainNameLabel != nil {
domainNameLabel = *input.DNSSettings.DomainNameLabel
}

if input.Name != nil {
name = *input.Name
}

if input.PublicIPPrefix != nil && input.PublicIPPrefix.ID != nil {
publicIPPrefixId = *input.PublicIPPrefix.ID
}

if input.PublicIPAddressVersion != "" {
version = string(input.PublicIPAddressVersion)
}

var idleTimeoutInMinutes int
if input.IdleTimeoutInMinutes != nil {
idleTimeoutInMinutes = int(*input.IdleTimeoutInMinutes)
}

return VirtualMachineScaleSetNetworkInterfaceIPConfigurationPublicIPAddress{
Name: name,
DomainNameLabel: domainNameLabel,
IdleTimeoutInMinutes: idleTimeoutInMinutes,
IPTag: ipTags,
PublicIpPrefixId: publicIPPrefixId,
Version: version,
}
}

func flattenOrchestratedVirtualMachineScaleSetIdentityToModel(input *compute.VirtualMachineScaleSetIdentity) ([]identity.ModelUserAssigned, error) {
if input == nil {
return nil, nil
}

identityIds := make(map[string]identity.UserAssignedIdentityDetails, 0)
for k, v := range input.UserAssignedIdentities {
if v != nil {
identityIds[k] = identity.UserAssignedIdentityDetails{
ClientId: v.ClientID,
PrincipalId: v.PrincipalID,
}
}
}

tmp := identity.UserAssignedMap{
Type: input.Type,
IdentityIds: identityIds,
}

output, err := identity.FlattenUserAssignedMapToModel(&tmp)
if err != nil {
return nil, fmt.Errorf("expanding `identity`: %+v", err)
}

return *output, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package compute_test

import (
"fmt"
"testing"

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

type OrchestratedVirtualMachineScaleSetDataSource struct{}

func TestAccOrchestratedVMSSDataSource_complete(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurerm_orchestrated_virtual_machine_scale_set", "test")
d := OrchestratedVirtualMachineScaleSetDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: d.complete(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("location").HasValue(data.Locations.Primary),
check.That(data.ResourceName).Key("network_interfaces.#").HasValue("1"),
),
},
})
}

func (OrchestratedVirtualMachineScaleSetDataSource) complete(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

data azurerm_orchestrated_virtual_machine_scale_set test {
name = azurerm_service_plan.test.name
resource_group_name = azurerm_service_plan.test.resource_group_name
}
`, OrchestratedVirtualMachineScaleSetResource{}.linuxInstances(data))
}
4 changes: 3 additions & 1 deletion internal/services/compute/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource {
}

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

func (r Registration) Resources() []sdk.Resource {
Expand Down
Loading