diff --git a/internal/sdk/resource.go b/internal/sdk/resource.go index e961ed38d192..9a8ab4757c41 100644 --- a/internal/sdk/resource.go +++ b/internal/sdk/resource.go @@ -48,6 +48,19 @@ type DataSource interface { Read() ResourceFunc } +// DataSourceWithDeprecationReplacedBy is an optional interface +// +// DataSource implementing this interface will be marked as Deprecated +// and output the DeprecationMessage during Terraform operations. +type DataSourceWithDeprecationReplacedBy interface { + DataSource + + // nolint gocritic + // DeprecatedInFavourOfDataSource returns the name of the resource that this has been deprecated in favour of + // NOTE: this must return a non-empty string + DeprecatedInFavourOfDataSource() string +} + // A Resource is an object which can be provisioned and managed by Terraform // that is, Created, Retrieved, Deleted, Imported (and optionally, Updated, by implementing // the 'ResourceWithUpdate' interface) diff --git a/internal/sdk/wrapper_data_source.go b/internal/sdk/wrapper_data_source.go index 3e23582a1d15..f7a1bfe9fac1 100644 --- a/internal/sdk/wrapper_data_source.go +++ b/internal/sdk/wrapper_data_source.go @@ -52,6 +52,19 @@ func (dw *DataSourceWrapper) DataSource() (*schema.Resource, error) { }, } + if v, ok := dw.dataSource.(DataSourceWithDeprecationReplacedBy); ok { + replacementDataSourceType := v.DeprecatedInFavourOfDataSource() + if replacementDataSourceType == "" { + return nil, fmt.Errorf("datasource %q must return a non-empty DeprecatedInFavourOfDataSource if implementing DataSourceWithDeprecationReplacedBy", dw.dataSource.ResourceType()) + } + resource.DeprecationMessage = fmt.Sprintf(`The %[1]q datasource has been deprecated and replaced by the %[2]q datasource. + +The existing %[1]q datasource will remain available until the next +major version of the Azure Provider however the existing datasource is feature-frozen +and we recommend using the %[2]q datasource instead. +`, dw.dataSource.ResourceType(), replacementDataSourceType) + } + return &resource, nil } diff --git a/internal/services/hybridcompute/arc_machine_data_source.go b/internal/services/hybridcompute/arc_machine_data_source.go new file mode 100644 index 000000000000..c9131d2b0083 --- /dev/null +++ b/internal/services/hybridcompute/arc_machine_data_source.go @@ -0,0 +1,846 @@ +package hybridcompute + +import ( + "context" + "fmt" + "strconv" + "time" + + "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-sdk/resource-manager/hybridcompute/2022-11-10/machines" + "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" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type ArcMachineModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + AgentConfiguration []AgentConfigurationModel `tfschema:"agent"` + ClientPublicKey string `tfschema:"client_public_key"` + CloudMetadata []CloudMetadataModel `tfschema:"cloud_metadata"` + DetectedProperties map[string]string `tfschema:"detected_properties"` + Location string `tfschema:"location"` + LocationData []LocationDataModel `tfschema:"location_data"` + MssqlDiscovered bool `tfschema:"mssql_discovered"` + OsProfile []OSProfileModel `tfschema:"os_profile"` + OsType string `tfschema:"os_type"` + ParentClusterResourceId string `tfschema:"parent_cluster_resource_id"` + PrivateLinkScopeResourceId string `tfschema:"private_link_scope_resource_id"` + ServiceStatuses []ServiceStatusesModel `tfschema:"service_status"` + Tags map[string]string `tfschema:"tags"` + VmId string `tfschema:"vm_id"` + AdFqdn string `tfschema:"active_directory_fqdn"` + AgentVersion string `tfschema:"agent_version"` + DisplayName string `tfschema:"display_name"` + DnsFqdn string `tfschema:"dns_fqdn"` + DomainName string `tfschema:"domain_name"` + LastStatusChange string `tfschema:"last_status_change_time"` + MachineFqdn string `tfschema:"machine_fqdn"` + OsName string `tfschema:"os_name"` + OsSku string `tfschema:"os_sku"` + OsVersion string `tfschema:"os_version"` + Status machines.StatusTypes `tfschema:"status"` + VmUuid string `tfschema:"vm_uuid"` +} + +type AgentConfigurationModel struct { + ExtensionsAllowList []ConfigurationExtensionModel `tfschema:"extensions_allow_list"` + ExtensionsBlockList []ConfigurationExtensionModel `tfschema:"extensions_block_list"` + ExtensionsEnabled bool `tfschema:"extensions_enabled"` + GuestConfigurationEnabled bool `tfschema:"guest_configuration_enabled"` + IncomingConnectionsPorts []string `tfschema:"incoming_connections_ports"` + ProxyBypass []string `tfschema:"proxy_bypass"` + ProxyUrl string `tfschema:"proxy_url"` +} + +type ConfigurationExtensionModel struct { + Publisher string `tfschema:"publisher"` + Type string `tfschema:"type"` +} + +type CloudMetadataModel struct { + Provider string `tfschema:"provider"` +} + +type LocationDataModel struct { + City string `tfschema:"city"` + CountryOrRegion string `tfschema:"country_or_region"` + District string `tfschema:"district"` + Name string `tfschema:"name"` +} + +type OSProfileModel struct { + ComputerName string `tfschema:"computer_name"` + LinuxConfiguration []OSProfileLinuxConfigurationModel `tfschema:"linux"` + WindowsConfiguration []OSProfileWindowsConfigurationModel `tfschema:"windows"` +} + +type OSProfileLinuxConfigurationModel struct { + PatchSettings []PatchSettingsModel `tfschema:"patch"` +} + +type PatchSettingsModel struct { + AssessmentMode machines.AssessmentModeTypes `tfschema:"assessment_mode"` + PatchMode machines.PatchModeTypes `tfschema:"patch_mode"` +} + +type OSProfileWindowsConfigurationModel struct { + PatchSettings []PatchSettingsModel `tfschema:"patch"` +} + +type ServiceStatusesModel struct { + ExtensionService []ServiceStatusModel `tfschema:"extension_service"` + GuestConfigurationService []ServiceStatusModel `tfschema:"guest_configuration_service"` +} + +type ServiceStatusModel struct { + StartupType string `tfschema:"startup_type"` + Status string `tfschema:"status"` +} + +type ArcMachineDataSource struct{} + +var _ sdk.DataSource = ArcMachineDataSource{} + +func (a ArcMachineDataSource) Arguments() map[string]*schema.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": commonschema.ResourceGroupNameForDataSource(), + } +} + +func (a ArcMachineDataSource) Attributes() map[string]*schema.Schema { + return map[string]*pluginsdk.Schema{ + "agent": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "extensions_allow_list": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "publisher": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "extensions_block_list": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "publisher": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "extensions_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "guest_configuration_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "incoming_connections_ports": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "proxy_bypass": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "proxy_url": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "active_directory_fqdn": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "agent_version": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "client_public_key": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "cloud_metadata": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "provider": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "detected_properties": { + Type: pluginsdk.TypeMap, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + + "display_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "dns_fqdn": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "domain_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "identity": commonschema.SystemAssignedIdentityComputed(), + + "last_status_change_time": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "location": commonschema.LocationComputed(), + + "location_data": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "city": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "country_or_region": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "district": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "machine_fqdn": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "mssql_discovered": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "os_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "os_profile": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "computer_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "linux": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "patch": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "assessment_mode": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "patch_mode": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + + "windows": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "patch": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "assessment_mode": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "patch_mode": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + + "os_sku": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "os_type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "os_version": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "parent_cluster_resource_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "private_link_scope_resource_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "service_status": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "extension_service": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "startup_type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "guest_configuration_service": { + Type: pluginsdk.TypeList, + Computed: true, + + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "startup_type": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + + "status": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "vm_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "vm_uuid": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "tags": commonschema.TagsDataSource(), + } +} + +func (a ArcMachineDataSource) ModelObject() interface{} { + return &ArcMachineDataSource{} +} + +func (a ArcMachineDataSource) ResourceType() string { + return "azurerm_arc_machine" +} + +func (a ArcMachineDataSource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.HybridCompute.MachinesClient + subscriptionId := metadata.Client.Account.SubscriptionId + + var arcMachineModel ArcMachineModel + if err := metadata.Decode(&arcMachineModel); err != nil { + return err + } + + id := machines.NewMachineID(subscriptionId, arcMachineModel.ResourceGroupName, arcMachineModel.Name) + + resp, err := client.Get(ctx, id, machines.GetOperationOptions{}) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("%s was not found", id) + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + model := resp.Model + if model == nil { + return fmt.Errorf("retrieving %s: model was nil", id) + } + + state := ArcMachineModel{ + Name: id.MachineName, + ResourceGroupName: id.ResourceGroupName, + Location: location.Normalize(model.Location), + } + + identityValue := identity.FlattenSystemAssigned(model.Identity) + + if err := metadata.ResourceData.Set("identity", identityValue); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + + if properties := model.Properties; properties != nil { + if properties.AdFqdn != nil { + state.AdFqdn = *properties.AdFqdn + } + + agentConfigurationValue, err := flattenAgentConfigurationModel(properties.AgentConfiguration) + if err != nil { + return err + } + + state.AgentConfiguration = agentConfigurationValue + + if properties.AgentVersion != nil { + state.AgentVersion = *properties.AgentVersion + } + + if properties.ClientPublicKey != nil { + state.ClientPublicKey = *properties.ClientPublicKey + } + + cloudMetadataValue := flattenCloudMetadataModel(properties.CloudMetadata) + + state.CloudMetadata = cloudMetadataValue + + if properties.DetectedProperties != nil { + state.DetectedProperties = *properties.DetectedProperties + } + + if properties.DisplayName != nil { + state.DisplayName = *properties.DisplayName + } + + if properties.DnsFqdn != nil { + state.DnsFqdn = *properties.DnsFqdn + } + + if properties.DomainName != nil { + state.DomainName = *properties.DomainName + } + + if properties.ErrorDetails != nil { + if len(*properties.ErrorDetails) > 0 { + return fmt.Errorf("retrieving %s: error details: %+v", id, *properties.ErrorDetails) + } + } + + if properties.LastStatusChange != nil { + state.LastStatusChange = *properties.LastStatusChange + } + + locationDataValue := flattenLocationDataModel(properties.LocationData) + + state.LocationData = locationDataValue + + if properties.MachineFqdn != nil { + state.MachineFqdn = *properties.MachineFqdn + } + + if properties.MssqlDiscovered != nil { + state.MssqlDiscovered, err = strconv.ParseBool(*properties.MssqlDiscovered) + if err != nil { + return err + } + } + + if properties.OsName != nil { + state.OsName = *properties.OsName + } + + osProfileValue := flattenOSProfileModel(properties.OsProfile) + + state.OsProfile = osProfileValue + + if properties.OsSku != nil { + state.OsSku = *properties.OsSku + } + + if properties.OsType != nil { + state.OsType = *properties.OsType + } + + if properties.OsVersion != nil { + state.OsVersion = *properties.OsVersion + } + + if properties.ParentClusterResourceId != nil { + state.ParentClusterResourceId = *properties.ParentClusterResourceId + } + + if properties.PrivateLinkScopeResourceId != nil { + state.PrivateLinkScopeResourceId = *properties.PrivateLinkScopeResourceId + } + + serviceStatusesValue := flattenServiceStatusesModel(properties.ServiceStatuses) + + state.ServiceStatuses = serviceStatusesValue + + if properties.Status != nil { + state.Status = *properties.Status + } + + if properties.VMId != nil { + state.VmId = *properties.VMId + } + + if properties.VMUuid != nil { + state.VmUuid = *properties.VMUuid + } + } + if model.Tags != nil { + state.Tags = *model.Tags + } + + metadata.SetID(id) + return metadata.Encode(&state) + }, + } +} + +func flattenAgentConfigurationModel(input *machines.AgentConfiguration) ([]AgentConfigurationModel, error) { + var outputList []AgentConfigurationModel + if input == nil { + return outputList, nil + } + + output := AgentConfigurationModel{} + + extensionsAllowListValue := flattenConfigurationExtensionModel(input.ExtensionsAllowList) + + output.ExtensionsAllowList = extensionsAllowListValue + + extensionsBlockListValue := flattenConfigurationExtensionModel(input.ExtensionsBlockList) + + output.ExtensionsBlockList = extensionsBlockListValue + + if input.ExtensionsEnabled != nil { + parsedBool, err := strconv.ParseBool(*input.ExtensionsEnabled) + if err != nil { + return nil, err + } + output.ExtensionsEnabled = parsedBool + } + + if input.GuestConfigurationEnabled != nil { + parsedBool, err := strconv.ParseBool(*input.GuestConfigurationEnabled) + if err != nil { + return nil, err + } + output.GuestConfigurationEnabled = parsedBool + } + + if input.IncomingConnectionsPorts != nil { + output.IncomingConnectionsPorts = *input.IncomingConnectionsPorts + } + + if input.ProxyBypass != nil { + output.ProxyBypass = *input.ProxyBypass + } + + if input.ProxyUrl != nil { + output.ProxyUrl = *input.ProxyUrl + } + + return append(outputList, output), nil +} + +func flattenConfigurationExtensionModel(inputList *[]machines.ConfigurationExtension) []ConfigurationExtensionModel { + var outputList []ConfigurationExtensionModel + if inputList == nil { + return outputList + } + + for _, input := range *inputList { + output := ConfigurationExtensionModel{} + + if input.Publisher != nil { + output.Publisher = *input.Publisher + } + + if input.Type != nil { + output.Type = *input.Type + } + + outputList = append(outputList, output) + } + + return outputList +} + +func flattenCloudMetadataModel(input *machines.CloudMetadata) []CloudMetadataModel { + var outputList []CloudMetadataModel + if input == nil { + return outputList + } + + output := CloudMetadataModel{} + + if input.Provider != nil { + output.Provider = *input.Provider + } + + return append(outputList, output) +} + +func flattenLocationDataModel(input *machines.LocationData) []LocationDataModel { + var outputList []LocationDataModel + if input == nil { + return outputList + } + + output := LocationDataModel{ + Name: input.Name, + } + + if input.City != nil { + output.City = *input.City + } + + if input.CountryOrRegion != nil { + output.CountryOrRegion = *input.CountryOrRegion + } + + if input.District != nil { + output.District = *input.District + } + + return append(outputList, output) +} + +func flattenOSProfileModel(input *machines.OSProfile) []OSProfileModel { + var outputList []OSProfileModel + if input == nil { + return outputList + } + + output := OSProfileModel{} + + if input.ComputerName != nil { + output.ComputerName = *input.ComputerName + } + + linuxConfigurationValue := flattenOSProfileLinuxConfigurationModel(input.LinuxConfiguration) + + output.LinuxConfiguration = linuxConfigurationValue + + windowsConfigurationValue := flattenOSProfileWindowsConfigurationModel(input.WindowsConfiguration) + output.WindowsConfiguration = windowsConfigurationValue + + return append(outputList, output) +} + +func flattenOSProfileLinuxConfigurationModel(input *machines.OSProfileLinuxConfiguration) []OSProfileLinuxConfigurationModel { + var outputList []OSProfileLinuxConfigurationModel + if input == nil { + return outputList + } + + output := OSProfileLinuxConfigurationModel{} + + patchSettingsValue := flattenPatchSettingsModel(input.PatchSettings) + + output.PatchSettings = patchSettingsValue + + return append(outputList, output) +} + +func flattenPatchSettingsModel(input *machines.PatchSettings) []PatchSettingsModel { + var outputList []PatchSettingsModel + if input == nil { + return outputList + } + + output := PatchSettingsModel{} + + if input.AssessmentMode != nil { + output.AssessmentMode = *input.AssessmentMode + } + + if input.PatchMode != nil { + output.PatchMode = *input.PatchMode + } + + return append(outputList, output) +} + +func flattenOSProfileWindowsConfigurationModel(input *machines.OSProfileWindowsConfiguration) []OSProfileWindowsConfigurationModel { + var outputList []OSProfileWindowsConfigurationModel + if input == nil { + return outputList + } + + output := OSProfileWindowsConfigurationModel{} + patchSettingsValue := flattenPatchSettingsModel(input.PatchSettings) + output.PatchSettings = patchSettingsValue + + return append(outputList, output) +} + +func flattenServiceStatusesModel(input *machines.ServiceStatuses) []ServiceStatusesModel { + var outputList []ServiceStatusesModel + if input == nil { + return outputList + } + + output := ServiceStatusesModel{} + + extensionServiceValue := flattenServiceStatusModel(input.ExtensionService) + output.ExtensionService = extensionServiceValue + + guestConfigurationServiceValue := flattenServiceStatusModel(input.GuestConfigurationService) + output.GuestConfigurationService = guestConfigurationServiceValue + + return append(outputList, output) +} + +func flattenServiceStatusModel(input *machines.ServiceStatus) []ServiceStatusModel { + var outputList []ServiceStatusModel + if input == nil { + return outputList + } + + output := ServiceStatusModel{} + + if input.StartupType != nil { + output.StartupType = *input.StartupType + } + + if input.Status != nil { + output.Status = *input.Status + } + + return append(outputList, output) +} diff --git a/internal/services/hybridcompute/arc_machine_data_source_test.go b/internal/services/hybridcompute/arc_machine_data_source_test.go new file mode 100644 index 000000000000..70711f0b68dd --- /dev/null +++ b/internal/services/hybridcompute/arc_machine_data_source_test.go @@ -0,0 +1,205 @@ +package hybridcompute_test + +import ( + "fmt" + "math/rand" + "os" + "testing" + + "github.com/hashicorp/go-uuid" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type ArcMachineDataSource struct{} + +const LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const NumberBytes = "1234567890" +const SpecialBytes = "!@#$%^()" + +func generateRandomPassword(n int) string { + b := make([]byte, n) + for i := range b { + r := rand.Int() + switch r % 3 { + case 0: + b[i] = LetterBytes[rand.Intn(len(LetterBytes))] + case 1: + b[i] = SpecialBytes[rand.Intn(len(SpecialBytes))] + case 2: + b[i] = NumberBytes[rand.Intn(len(NumberBytes))] + } + } + return string(b) +} + +func TestAccArcMachine_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_arc_machine", "test") + d := ArcMachineDataSource{} + clientSecret := os.Getenv("ARM_CLIENT_SECRET") + randomUUID, _ := uuid.GenerateUUID() + password := generateRandomPassword(15) + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: d.basic(data, clientSecret, randomUUID, password), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("agent.#").HasValue("1"), + check.That(data.ResourceName).Key("mssql_discovered").HasValue("false"), + check.That(data.ResourceName).Key("os_name").HasValue("linux"), + check.That(data.ResourceName).Key("os_profile.#").HasValue("1"), + ), + }, + }) +} + +func (r ArcMachineDataSource) template(data acceptance.TestData, secret string, randomUUID string, password string) string { + return fmt.Sprintf(` +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } +} + +data "azurerm_client_config" "current" {} + +# note: real-life usage prefer random_uuid resource in registry.terraform.io/hashicorp/random +locals { + random_uuid = "%s" +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnw-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.2.0/24"] +} + +resource "azurerm_network_interface" "test" { + name = "acctestnic-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "internal" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.test.id + } +} + +resource "azurerm_network_security_group" "my_terraform_nsg" { + name = "myNetworkSecurityGroup" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + security_rule { + name = "SSH" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +resource "azurerm_network_interface_security_group_association" "example" { + network_interface_id = azurerm_network_interface.test.id + network_security_group_id = azurerm_network_security_group.my_terraform_nsg.id +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Static" +} + +resource "azurerm_linux_virtual_machine" "test" { + name = "acctestVM-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + size = "Standard_F2" + admin_username = "adminuser" + admin_password = "%s" + provision_vm_agent = false + allow_extension_operations = false + disable_password_authentication = false + network_interface_ids = [ + azurerm_network_interface.test.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "18.04-LTS" + version = "latest" + } + + connection { + type = "ssh" + host = azurerm_public_ip.test.ip_address + user = "adminuser" + password = "%s" + } + + provisioner "file" { + content = templatefile("scripts/install_arc.sh.tftpl", { + resource_group_name = azurerm_resource_group.test.name + uuid = local.random_uuid + location = azurerm_resource_group.test.location + tenant_id = data.azurerm_client_config.current.tenant_id + client_id = data.azurerm_client_config.current.client_id + client_secret = "%s" + subscription_id = data.azurerm_client_config.current.subscription_id + }) + destination = "/home/adminuser/install_arc_agent.sh" + } + + provisioner "remote-exec" { + inline = [ + "sudo apt-get install -y python-ctypes", + "sudo sed -i 's/\r$//' /home/adminuser/install_arc_agent.sh", + "sudo chmod +x /home/adminuser/install_arc_agent.sh", + "bash /home/adminuser/install_arc_agent.sh", + ] + } +} +`, randomUUID, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, password, password, secret) +} + +func (r ArcMachineDataSource) basic(data acceptance.TestData, secret string, randomUUID string, password string) string { + template := r.template(data, secret, randomUUID, password) + return fmt.Sprintf(` + %s + +data "azurerm_arc_machine" "test" { + name = azurerm_linux_virtual_machine.test.name + resource_group_name = azurerm_resource_group.test.name + depends_on = [ + azurerm_linux_virtual_machine.test + ] +} +`, template) +} diff --git a/internal/services/hybridcompute/hybrid_compute_machine_data_source.go b/internal/services/hybridcompute/hybrid_compute_machine_data_source.go index 84ad5107858c..90268a519f61 100644 --- a/internal/services/hybridcompute/hybrid_compute_machine_data_source.go +++ b/internal/services/hybridcompute/hybrid_compute_machine_data_source.go @@ -17,108 +17,115 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) +// HybridComputeMachineModel is deprecated and will be removed after 4.0 version. +// Please add new features to azurerm_arc_machine instead. + type HybridComputeMachineModel struct { - Name string `tfschema:"name"` - ResourceGroupName string `tfschema:"resource_group_name"` - AgentConfiguration []AgentConfigurationModel `tfschema:"agent_configuration"` - ClientPublicKey string `tfschema:"client_public_key"` - CloudMetadata []CloudMetadataModel `tfschema:"cloud_metadata"` - DetectedProperties map[string]string `tfschema:"detected_properties"` - Location string `tfschema:"location"` - LocationData []LocationDataModel `tfschema:"location_data"` - MssqlDiscovered bool `tfschema:"mssql_discovered"` - OsProfile []OSProfileModel `tfschema:"os_profile"` - OsType string `tfschema:"os_type"` - ParentClusterResourceId string `tfschema:"parent_cluster_resource_id"` - PrivateLinkScopeResourceId string `tfschema:"private_link_scope_resource_id"` - ServiceStatuses []ServiceStatusesModel `tfschema:"service_status"` - Tags map[string]string `tfschema:"tags"` - VmId string `tfschema:"vm_id"` - AdFqdn string `tfschema:"ad_fqdn"` - AgentVersion string `tfschema:"agent_version"` - DisplayName string `tfschema:"display_name"` - DnsFqdn string `tfschema:"dns_fqdn"` - DomainName string `tfschema:"domain_name"` - ErrorDetails []ErrorDetailModel `tfschema:"error_details"` - LastStatusChange string `tfschema:"last_status_change"` - MachineFqdn string `tfschema:"machine_fqdn"` - OsName string `tfschema:"os_name"` - OsSku string `tfschema:"os_sku"` - OsVersion string `tfschema:"os_version"` - Status machines.StatusTypes `tfschema:"status"` - VmUuid string `tfschema:"vm_uuid"` -} - -type AgentConfigurationModel struct { - ExtensionsAllowList []ConfigurationExtensionModel `tfschema:"extensions_allow_list"` - ExtensionsBlockList []ConfigurationExtensionModel `tfschema:"extensions_block_list"` - ExtensionsEnabled bool `tfschema:"extensions_enabled"` - GuestConfigurationEnabled bool `tfschema:"guest_configuration_enabled"` - IncomingConnectionsPorts []string `tfschema:"incoming_connections_ports"` - ProxyBypass []string `tfschema:"proxy_bypass"` - ProxyUrl string `tfschema:"proxy_url"` -} - -type ConfigurationExtensionModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + AgentConfiguration []DeprecatedAgentConfigurationModel `tfschema:"agent_configuration"` + ClientPublicKey string `tfschema:"client_public_key"` + CloudMetadata []DeprecatedCloudMetadataModel `tfschema:"cloud_metadata"` + DetectedProperties map[string]string `tfschema:"detected_properties"` + Location string `tfschema:"location"` + LocationData []DeprecatedLocationDataModel `tfschema:"location_data"` + MssqlDiscovered bool `tfschema:"mssql_discovered"` + OsProfile []DeprecatedOSProfileModel `tfschema:"os_profile"` + OsType string `tfschema:"os_type"` + ParentClusterResourceId string `tfschema:"parent_cluster_resource_id"` + PrivateLinkScopeResourceId string `tfschema:"private_link_scope_resource_id"` + ServiceStatuses []DeprecatedServiceStatusesModel `tfschema:"service_status"` + Tags map[string]string `tfschema:"tags"` + VmId string `tfschema:"vm_id"` + AdFqdn string `tfschema:"ad_fqdn"` + AgentVersion string `tfschema:"agent_version"` + DisplayName string `tfschema:"display_name"` + DnsFqdn string `tfschema:"dns_fqdn"` + DomainName string `tfschema:"domain_name"` + ErrorDetails []DeprecatedErrorDetailModel `tfschema:"error_details"` + LastStatusChange string `tfschema:"last_status_change"` + MachineFqdn string `tfschema:"machine_fqdn"` + OsName string `tfschema:"os_name"` + OsSku string `tfschema:"os_sku"` + OsVersion string `tfschema:"os_version"` + Status machines.StatusTypes `tfschema:"status"` + VmUuid string `tfschema:"vm_uuid"` +} + +type DeprecatedAgentConfigurationModel struct { + ExtensionsAllowList []DeprecatedConfigurationExtensionModel `tfschema:"extensions_allow_list"` + ExtensionsBlockList []DeprecatedConfigurationExtensionModel `tfschema:"extensions_block_list"` + ExtensionsEnabled bool `tfschema:"extensions_enabled"` + GuestConfigurationEnabled bool `tfschema:"guest_configuration_enabled"` + IncomingConnectionsPorts []string `tfschema:"incoming_connections_ports"` + ProxyBypass []string `tfschema:"proxy_bypass"` + ProxyUrl string `tfschema:"proxy_url"` +} + +type DeprecatedConfigurationExtensionModel struct { Publisher string `tfschema:"publisher"` Type string `tfschema:"type"` } -type CloudMetadataModel struct { +type DeprecatedCloudMetadataModel struct { Provider string `tfschema:"provider"` } -type LocationDataModel struct { +type DeprecatedLocationDataModel struct { City string `tfschema:"city"` CountryOrRegion string `tfschema:"country_or_region"` District string `tfschema:"district"` Name string `tfschema:"name"` } -type OSProfileModel struct { - ComputerName string `tfschema:"computer_name"` - LinuxConfiguration []OSProfileLinuxConfigurationModel `tfschema:"linux_configuration"` - WindowsConfiguration []OSProfileWindowsConfigurationModel `tfschema:"windows_configuration"` +type DeprecatedOSProfileModel struct { + ComputerName string `tfschema:"computer_name"` + LinuxConfiguration []DeprecatedOSProfileLinuxConfigurationModel `tfschema:"linux_configuration"` + WindowsConfiguration []DeprecatedOSProfileWindowsConfigurationModel `tfschema:"windows_configuration"` } -type OSProfileLinuxConfigurationModel struct { - PatchSettings []PatchSettingsModel `tfschema:"patch_settings"` +type DeprecatedOSProfileLinuxConfigurationModel struct { + PatchSettings []DeprecatedPatchSettingsModel `tfschema:"patch_settings"` } -type PatchSettingsModel struct { +type DeprecatedPatchSettingsModel struct { AssessmentMode machines.AssessmentModeTypes `tfschema:"assessment_mode"` PatchMode machines.PatchModeTypes `tfschema:"patch_mode"` } -type OSProfileWindowsConfigurationModel struct { - PatchSettings []PatchSettingsModel `tfschema:"patch_settings"` +type DeprecatedOSProfileWindowsConfigurationModel struct { + PatchSettings []DeprecatedPatchSettingsModel `tfschema:"patch_settings"` } -type ServiceStatusesModel struct { - ExtensionService []ServiceStatusModel `tfschema:"extension_service"` - GuestConfigurationService []ServiceStatusModel `tfschema:"guest_configuration_service"` +type DeprecatedServiceStatusesModel struct { + ExtensionService []DeprecatedServiceStatusModel `tfschema:"extension_service"` + GuestConfigurationService []DeprecatedServiceStatusModel `tfschema:"guest_configuration_service"` } -type ServiceStatusModel struct { +type DeprecatedServiceStatusModel struct { StartupType string `tfschema:"startup_type"` Status string `tfschema:"status"` } -type ErrorDetailModel struct { - AdditionalInfo []ErrorAdditionalInfoModel `tfschema:"additional_info"` - Code string `tfschema:"code"` - Message string `tfschema:"message"` - Target string `tfschema:"target"` +type DeprecatedErrorDetailModel struct { + AdditionalInfo []DeprecatedErrorAdditionalInfoModel `tfschema:"additional_info"` + Code string `tfschema:"code"` + Message string `tfschema:"message"` + Target string `tfschema:"target"` } -type ErrorAdditionalInfoModel struct { +type DeprecatedErrorAdditionalInfoModel struct { Info string `tfschema:"info"` Type string `tfschema:"type"` } type HybridComputeMachineDataSource struct{} -var _ sdk.DataSource = HybridComputeMachineDataSource{} +func (r HybridComputeMachineDataSource) DeprecatedInFavourOfDataSource() string { + return "azurerm_arc_machine" +} + +var _ sdk.DataSourceWithDeprecationReplacedBy = HybridComputeMachineDataSource{} func (r HybridComputeMachineDataSource) ResourceType() string { return "azurerm_hybrid_compute_machine" @@ -574,7 +581,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.AdFqdn = *properties.AdFqdn } - agentConfigurationValue, err := flattenAgentConfigurationModel(properties.AgentConfiguration) + agentConfigurationValue, err := deprecatedFlattenAgentConfigurationModel(properties.AgentConfiguration) if err != nil { return err } @@ -589,7 +596,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.ClientPublicKey = *properties.ClientPublicKey } - cloudMetadataValue := flattenCloudMetadataModel(properties.CloudMetadata) + cloudMetadataValue := deprecatedFlattenCloudMetadataModel(properties.CloudMetadata) state.CloudMetadata = cloudMetadataValue @@ -609,7 +616,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.DomainName = *properties.DomainName } - errorDetailsValue := flattenErrorDetailModel(properties.ErrorDetails) + errorDetailsValue := deprecatedFlattenErrorDetailModel(properties.ErrorDetails) state.ErrorDetails = errorDetailsValue @@ -617,7 +624,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.LastStatusChange = *properties.LastStatusChange } - locationDataValue := flattenLocationDataModel(properties.LocationData) + locationDataValue := deprecatedFlattenLocationDataModel(properties.LocationData) state.LocationData = locationDataValue @@ -636,7 +643,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.OsName = *properties.OsName } - osProfileValue := flattenOSProfileModel(properties.OsProfile) + osProfileValue := deprecatedFlattenOSProfileModel(properties.OsProfile) state.OsProfile = osProfileValue @@ -660,7 +667,7 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { state.PrivateLinkScopeResourceId = *properties.PrivateLinkScopeResourceId } - serviceStatusesValue := flattenServiceStatusesModel(properties.ServiceStatuses) + serviceStatusesValue := deprecatedFlattenServiceStatusesModel(properties.ServiceStatuses) state.ServiceStatuses = serviceStatusesValue @@ -686,19 +693,19 @@ func (r HybridComputeMachineDataSource) Read() sdk.ResourceFunc { } } -func flattenAgentConfigurationModel(input *machines.AgentConfiguration) ([]AgentConfigurationModel, error) { - var outputList []AgentConfigurationModel +func deprecatedFlattenAgentConfigurationModel(input *machines.AgentConfiguration) ([]DeprecatedAgentConfigurationModel, error) { + var outputList []DeprecatedAgentConfigurationModel if input == nil { return outputList, nil } - output := AgentConfigurationModel{} + output := DeprecatedAgentConfigurationModel{} - extensionsAllowListValue := flattenConfigurationExtensionModel(input.ExtensionsAllowList) + extensionsAllowListValue := deprecatedFlattenConfigurationExtensionModel(input.ExtensionsAllowList) output.ExtensionsAllowList = extensionsAllowListValue - extensionsBlockListValue := flattenConfigurationExtensionModel(input.ExtensionsBlockList) + extensionsBlockListValue := deprecatedFlattenConfigurationExtensionModel(input.ExtensionsBlockList) output.ExtensionsBlockList = extensionsBlockListValue @@ -733,14 +740,14 @@ func flattenAgentConfigurationModel(input *machines.AgentConfiguration) ([]Agent return append(outputList, output), nil } -func flattenConfigurationExtensionModel(inputList *[]machines.ConfigurationExtension) []ConfigurationExtensionModel { - var outputList []ConfigurationExtensionModel +func deprecatedFlattenConfigurationExtensionModel(inputList *[]machines.ConfigurationExtension) []DeprecatedConfigurationExtensionModel { + var outputList []DeprecatedConfigurationExtensionModel if inputList == nil { return outputList } for _, input := range *inputList { - output := ConfigurationExtensionModel{} + output := DeprecatedConfigurationExtensionModel{} if input.Publisher != nil { output.Publisher = *input.Publisher @@ -756,13 +763,13 @@ func flattenConfigurationExtensionModel(inputList *[]machines.ConfigurationExten return outputList } -func flattenCloudMetadataModel(input *machines.CloudMetadata) []CloudMetadataModel { - var outputList []CloudMetadataModel +func deprecatedFlattenCloudMetadataModel(input *machines.CloudMetadata) []DeprecatedCloudMetadataModel { + var outputList []DeprecatedCloudMetadataModel if input == nil { return outputList } - output := CloudMetadataModel{} + output := DeprecatedCloudMetadataModel{} if input.Provider != nil { output.Provider = *input.Provider @@ -771,16 +778,16 @@ func flattenCloudMetadataModel(input *machines.CloudMetadata) []CloudMetadataMod return append(outputList, output) } -func flattenErrorDetailModel(inputList *[]machines.ErrorDetail) []ErrorDetailModel { - var outputList []ErrorDetailModel +func deprecatedFlattenErrorDetailModel(inputList *[]machines.ErrorDetail) []DeprecatedErrorDetailModel { + var outputList []DeprecatedErrorDetailModel if inputList == nil { return outputList } for _, input := range *inputList { - output := ErrorDetailModel{} + output := DeprecatedErrorDetailModel{} - additionalInfoValue := flattenErrorAdditionalInfoModel(input.AdditionalInfo) + additionalInfoValue := deprecatedFlattenErrorAdditionalInfoModel(input.AdditionalInfo) output.AdditionalInfo = additionalInfoValue @@ -802,14 +809,14 @@ func flattenErrorDetailModel(inputList *[]machines.ErrorDetail) []ErrorDetailMod return outputList } -func flattenErrorAdditionalInfoModel(inputList *[]machines.ErrorAdditionalInfo) []ErrorAdditionalInfoModel { - var outputList []ErrorAdditionalInfoModel +func deprecatedFlattenErrorAdditionalInfoModel(inputList *[]machines.ErrorAdditionalInfo) []DeprecatedErrorAdditionalInfoModel { + var outputList []DeprecatedErrorAdditionalInfoModel if inputList == nil { return outputList } for _, input := range *inputList { - output := ErrorAdditionalInfoModel{} + output := DeprecatedErrorAdditionalInfoModel{} if input.Info != nil && *input.Info != nil { @@ -831,13 +838,13 @@ func flattenErrorAdditionalInfoModel(inputList *[]machines.ErrorAdditionalInfo) return outputList } -func flattenLocationDataModel(input *machines.LocationData) []LocationDataModel { - var outputList []LocationDataModel +func deprecatedFlattenLocationDataModel(input *machines.LocationData) []DeprecatedLocationDataModel { + var outputList []DeprecatedLocationDataModel if input == nil { return outputList } - output := LocationDataModel{ + output := DeprecatedLocationDataModel{ Name: input.Name, } @@ -856,50 +863,50 @@ func flattenLocationDataModel(input *machines.LocationData) []LocationDataModel return append(outputList, output) } -func flattenOSProfileModel(input *machines.OSProfile) []OSProfileModel { - var outputList []OSProfileModel +func deprecatedFlattenOSProfileModel(input *machines.OSProfile) []DeprecatedOSProfileModel { + var outputList []DeprecatedOSProfileModel if input == nil { return outputList } - output := OSProfileModel{} + output := DeprecatedOSProfileModel{} if input.ComputerName != nil { output.ComputerName = *input.ComputerName } - linuxConfigurationValue := flattenOSProfileLinuxConfigurationModel(input.LinuxConfiguration) + linuxConfigurationValue := deprecatedFlattenOSProfileLinuxConfigurationModel(input.LinuxConfiguration) output.LinuxConfiguration = linuxConfigurationValue - windowsConfigurationValue := flattenOSProfileWindowsConfigurationModel(input.WindowsConfiguration) + windowsConfigurationValue := deprecatedFlattenOSProfileWindowsConfigurationModel(input.WindowsConfiguration) output.WindowsConfiguration = windowsConfigurationValue return append(outputList, output) } -func flattenOSProfileLinuxConfigurationModel(input *machines.OSProfileLinuxConfiguration) []OSProfileLinuxConfigurationModel { - var outputList []OSProfileLinuxConfigurationModel +func deprecatedFlattenOSProfileLinuxConfigurationModel(input *machines.OSProfileLinuxConfiguration) []DeprecatedOSProfileLinuxConfigurationModel { + var outputList []DeprecatedOSProfileLinuxConfigurationModel if input == nil { return outputList } - output := OSProfileLinuxConfigurationModel{} + output := DeprecatedOSProfileLinuxConfigurationModel{} - patchSettingsValue := flattenPatchSettingsModel(input.PatchSettings) + patchSettingsValue := deprecatedFlattenPatchSettingsModel(input.PatchSettings) output.PatchSettings = patchSettingsValue return append(outputList, output) } -func flattenPatchSettingsModel(input *machines.PatchSettings) []PatchSettingsModel { - var outputList []PatchSettingsModel +func deprecatedFlattenPatchSettingsModel(input *machines.PatchSettings) []DeprecatedPatchSettingsModel { + var outputList []DeprecatedPatchSettingsModel if input == nil { return outputList } - output := PatchSettingsModel{} + output := DeprecatedPatchSettingsModel{} if input.AssessmentMode != nil { output.AssessmentMode = *input.AssessmentMode @@ -912,43 +919,43 @@ func flattenPatchSettingsModel(input *machines.PatchSettings) []PatchSettingsMod return append(outputList, output) } -func flattenOSProfileWindowsConfigurationModel(input *machines.OSProfileWindowsConfiguration) []OSProfileWindowsConfigurationModel { - var outputList []OSProfileWindowsConfigurationModel +func deprecatedFlattenOSProfileWindowsConfigurationModel(input *machines.OSProfileWindowsConfiguration) []DeprecatedOSProfileWindowsConfigurationModel { + var outputList []DeprecatedOSProfileWindowsConfigurationModel if input == nil { return outputList } - output := OSProfileWindowsConfigurationModel{} - patchSettingsValue := flattenPatchSettingsModel(input.PatchSettings) + output := DeprecatedOSProfileWindowsConfigurationModel{} + patchSettingsValue := deprecatedFlattenPatchSettingsModel(input.PatchSettings) output.PatchSettings = patchSettingsValue return append(outputList, output) } -func flattenServiceStatusesModel(input *machines.ServiceStatuses) []ServiceStatusesModel { - var outputList []ServiceStatusesModel +func deprecatedFlattenServiceStatusesModel(input *machines.ServiceStatuses) []DeprecatedServiceStatusesModel { + var outputList []DeprecatedServiceStatusesModel if input == nil { return outputList } - output := ServiceStatusesModel{} + output := DeprecatedServiceStatusesModel{} - extensionServiceValue := flattenServiceStatusModel(input.ExtensionService) + extensionServiceValue := deprecatedFlattenServiceStatusModel(input.ExtensionService) output.ExtensionService = extensionServiceValue - guestConfigurationServiceValue := flattenServiceStatusModel(input.GuestConfigurationService) + guestConfigurationServiceValue := deprecatedFlattenServiceStatusModel(input.GuestConfigurationService) output.GuestConfigurationService = guestConfigurationServiceValue return append(outputList, output) } -func flattenServiceStatusModel(input *machines.ServiceStatus) []ServiceStatusModel { - var outputList []ServiceStatusModel +func deprecatedFlattenServiceStatusModel(input *machines.ServiceStatus) []DeprecatedServiceStatusModel { + var outputList []DeprecatedServiceStatusModel if input == nil { return outputList } - output := ServiceStatusModel{} + output := DeprecatedServiceStatusModel{} if input.StartupType != nil { output.StartupType = *input.StartupType diff --git a/internal/services/hybridcompute/hybrid_compute_machine_data_source_test.go b/internal/services/hybridcompute/hybrid_compute_machine_data_source_test.go index 9a85e30bc46f..069276c929cb 100644 --- a/internal/services/hybridcompute/hybrid_compute_machine_data_source_test.go +++ b/internal/services/hybridcompute/hybrid_compute_machine_data_source_test.go @@ -2,7 +2,6 @@ package hybridcompute_test import ( "fmt" - "math/rand" "os" "testing" @@ -13,26 +12,6 @@ import ( type HybridComputeMachineDataSource struct{} -const LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -const NumberBytes = "1234567890" -const SpecialBytes = "!@#$%^()" - -func generateRandomPassword(n int) string { - b := make([]byte, n) - for i := range b { - r := rand.Int() - switch r % 3 { - case 0: - b[i] = LetterBytes[rand.Intn(len(LetterBytes))] - case 1: - b[i] = SpecialBytes[rand.Intn(len(SpecialBytes))] - case 2: - b[i] = NumberBytes[rand.Intn(len(NumberBytes))] - } - } - return string(b) -} - func TestAccHybridComputeMachine_basic(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_hybrid_compute_machine", "test") d := HybridComputeMachineDataSource{} diff --git a/internal/services/hybridcompute/registration.go b/internal/services/hybridcompute/registration.go index 77400764426d..27ed92a8a0ed 100644 --- a/internal/services/hybridcompute/registration.go +++ b/internal/services/hybridcompute/registration.go @@ -40,7 +40,10 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { // DataSources returns a list of Data Sources supported by this Service func (r Registration) DataSources() []sdk.DataSource { - return []sdk.DataSource{HybridComputeMachineDataSource{}} + return []sdk.DataSource{ + HybridComputeMachineDataSource{}, + ArcMachineDataSource{}, + } } // Resources returns a list of Resources supported by this Service diff --git a/website/docs/d/arc_machine.html.markdown b/website/docs/d/arc_machine.html.markdown new file mode 100644 index 000000000000..6c757666eadc --- /dev/null +++ b/website/docs/d/arc_machine.html.markdown @@ -0,0 +1,228 @@ +--- +subcategory: "Hybrid Compute" +layout: "azurerm" +page_title: "Azure Resource Manager: Data Source: azurerm_arc_machine" +description: |- + Gets information about an existing Azure Arc machine. +--- + +# Data Source: azurerm_arc_machine + +Use this data source to access information about an existing Azure Arc machine. + +## Example Usage + +```hcl +data "azurerm_arc_machine" "example" { + name = "existing-hcmachine" + resource_group_name = "existing-rg" +} + +output "id" { + value = data.azurerm_arc_machine.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of this Azure Arc machine. + +* `resource_group_name` - (Required) The name of the Resource Group where the Hybrid Compute exists. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Azure Arc machine. + +* `active_directory_fqdn` - Specifies the AD fully qualified display name. + +* `agent` - A `agent` block as defined below. + +* `agent_version` - The Azure Arc machine agent full version. + +* `client_public_key` - Public Key that the client provides to be used during initial resource onboarding. + +* `cloud_metadata` - A `cloud_metadata` block as defined below. + +* `detected_properties` - A `detected_properties` block as defined below. + +* `display_name` - Specifies the Azure Arc machine display name. + +* `dns_fqdn` - Specifies the DNS fully qualified display name. + +* `domain_name` - Specifies the Windows domain name. + +* `error_details` - A `error_details` block as defined below. + +* `identity` - A `identity` block as defined below. + +* `last_status_change_time` - The time of the last status change. + +* `location` - The Azure Region where the Azure Arc machine exists. + +* `location_data` - A `location_data` block as defined below. + +* `machine_fqdn` - Specifies the Azure Arc machine fully qualified display name. + +* `mssql_discovered` - Specifies whether any MS SQL instance is discovered on the machine. + +* `os_name` - The Operating System running on the Azure Arc machine. + +* `os_profile` - A `os_profile` block as defined below. + +* `os_sku` - Specifies the Operating System product SKU. + +* `os_type` - The type of Operating System. Possible values are `windows` and `linux`. + +* `os_version` - The version of Operating System running on the Azure Arc machine. + +* `parent_cluster_resource_id` - The resource id of the parent cluster (Azure HCI) this machine is assigned to, if any. + +* `private_link_scope_resource_id` - The resource id of the parent cluster (Azure HCI) this machine is assigned to, if any. + +* `service_status` - A `service_status` block as defined below. + +* `status` - The status of the Azure Arc machine agent. + +* `tags` - A mapping of tags assigned to the Hybrid Compute. + +* `vm_id` - Specifies the Azure Arc machine unique ID. + +* `vm_uuid` - Specifies the Arc Machine's unique SMBIOS ID. + +--- + +A `agent` block exports the following: + +* `extensions_allow_list` - A `extensions_allow_list` block as defined below. + +* `extensions_block_list` - A `extensions_block_list` block as defined below. + +* `extensions_enabled` - Specifies whether the extension service is enabled or disabled. + +* `guest_configuration_enabled` - Specified whether the guest configuration service is enabled or disabled. + +* `incoming_connections_ports` - Specifies the list of ports that the agent will be able to listen on. + +* `proxy_bypass` - List of service names which should not use the specified proxy server. + +* `proxy_url` - Specifies the URL of the proxy to be used. + +--- + +A `cloud_metadata` block exports the following: + +* `provider` - Specifies the cloud provider. For example `Azure`, `AWS` and `GCP`. + +--- + +A `error_details` block exports the following: + +* `additional_info` - A `additional_info` block as defined above. + +* `code` - The error code. + +* `message` - The error message. + +* `target` - The error target. + +--- + +A `extension_service` block exports the following: + +* `startup_type` - The behavior of the service when the Arc-enabled machine starts up. + +* `status` - The current status of the service. + +--- + +A `extensions_allow_list` block exports the following: + +* `publisher` - Publisher of the extension. + +* `type` - Type of the extension. + +--- + +A `extensions_block_list` block exports the following: + +* `publisher` - Publisher of the extension. + +* `type` - Type of the extension. + +--- + +A `guest_configuration_service` block exports the following: + +* `startup_type` - The behavior of the service when the Arc-enabled machine starts up. + +* `status` - The current status of the service. + +--- + +A `identity` block exports the following: + +* `principal_id` - The principal ID of resource identity. + +* `tenant_id` - The tenant ID of resource. + +* `type` - The identity type. + +--- + +A `linux` block exports the following: + +* `patch` - A `patch` block as defined below. + +--- + +A `location_data` block exports the following: + +* `city` - The city or locality where the resource is located. + +* `country_or_region` - The country or region where the resource is located. + +* `district` - The district, state, or province where the resource is located. + +* `name` - A canonical name for the geographic or physical location. + +--- + +A `os_profile` block exports the following: + +* `computer_name` - Specifies the host OS name of the Azure Arc machine. + +* `linux` - A `linux` block as defined above. + +* `windows` - A `windows` block as defined below. + +--- + +A `patch` block exports the following: + +* `assessment_mode` - Specifies the assessment mode. + +* `patch_mode` - Specifies the patch mode. + +--- + +A `service_status` block exports the following: + +* `extension_service` - A `extension_service` block as defined above. + +* `guest_configuration_service` - A `guest_configuration_service` block as defined above. + +--- + +A `windows` block exports the following: + +* `patch` - A `patch` block as defined above. + +## 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 Azure Arc machine. diff --git a/website/docs/d/hybrid_compute_machine.html.markdown b/website/docs/d/hybrid_compute_machine.html.markdown index 6ea70c2df724..1305d4d92409 100644 --- a/website/docs/d/hybrid_compute_machine.html.markdown +++ b/website/docs/d/hybrid_compute_machine.html.markdown @@ -10,6 +10,10 @@ description: |- Use this data source to access information about an existing Hybrid Compute. +## Disclaimers + +-> **Note:** The Data Source `azurerm_hybrid_compute_machine` is deprecated will be removed in v4.0 of the Azure Provider - a replacement can be found in the form of the [`azurerm_arc_machine`](arc_machine.html) Data Source. + ## Example Usage ```hcl