From 3a3a3ab06e446816d08cea8935a702897a653622 Mon Sep 17 00:00:00 2001 From: Catriona Date: Fri, 21 Apr 2023 18:56:32 +0100 Subject: [PATCH 1/5] sql vm high availability --- internal/services/mssql/client/client.go | 62 ++- ...hine_availability_group_listener_schema.go | 154 ++++++ .../mssql_virtual_machine_group_schema.go | 95 ++++ ...ne_availability_group_listener_resource.go | 482 ++++++++++++++++++ ...ailability_group_listener_resource_test.go | 82 +++ .../mssql_virtual_machine_group_resource.go | 340 ++++++++++++ ...sql_virtual_machine_group_resource_test.go | 165 ++++++ .../mssql/mssql_virtual_machine_resource.go | 112 +++- internal/services/mssql/registration.go | 2 + .../availabilitygrouplisteners/README.md | 82 +++ .../availabilitygrouplisteners/client.go | 18 + .../availabilitygrouplisteners/constants.go | 121 +++++ .../id_availabilitygrouplistener.go | 140 +++++ .../id_sqlvirtualmachinegroup.go | 127 +++++ .../method_createorupdate_autorest.go | 79 +++ .../method_delete_autorest.go | 78 +++ .../method_get_autorest.go | 97 ++++ .../method_listbygroup_autorest.go | 186 +++++++ .../model_agconfiguration.go | 8 + .../model_agreplica.go | 12 + .../model_availabilitygrouplistener.go | 16 + ...del_availabilitygrouplistenerproperties.go | 14 + .../model_loadbalancerconfiguration.go | 12 + .../model_multisubnetipconfiguration.go | 9 + .../model_privateipaddress.go | 9 + .../availabilitygrouplisteners/predicates.go | 27 + .../availabilitygrouplisteners/version.go | 12 + .../sqlvirtualmachinegroups/README.md | 116 +++++ .../sqlvirtualmachinegroups/client.go | 18 + .../sqlvirtualmachinegroups/constants.go | 137 +++++ .../id_sqlvirtualmachinegroup.go | 127 +++++ .../method_createorupdate_autorest.go | 79 +++ .../method_delete_autorest.go | 78 +++ .../method_get_autorest.go | 68 +++ .../method_list_autorest.go | 187 +++++++ .../method_listbyresourcegroup_autorest.go | 187 +++++++ .../method_update_autorest.go | 79 +++ .../model_sqlvirtualmachinegroup.go | 18 + .../model_sqlvirtualmachinegroupproperties.go | 14 + .../model_sqlvirtualmachinegroupupdate.go | 8 + .../model_wsfcdomainprofile.go | 16 + .../sqlvirtualmachinegroups/predicates.go | 32 ++ .../sqlvirtualmachinegroups/version.go | 12 + vendor/modules.txt | 2 + 44 files changed, 3689 insertions(+), 30 deletions(-) create mode 100644 internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go create mode 100644 internal/services/mssql/helper/mssql_virtual_machine_group_schema.go create mode 100644 internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go create mode 100644 internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go create mode 100644 internal/services/mssql/mssql_virtual_machine_group_resource.go create mode 100644 internal/services/mssql/mssql_virtual_machine_group_resource_test.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/README.md create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/client.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/constants.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_createorupdate_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_delete_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_get_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_listbygroup_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agconfiguration.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agreplica.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistener.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistenerproperties.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_loadbalancerconfiguration.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_multisubnetipconfiguration.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_privateipaddress.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/version.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/README.md create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/client.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/constants.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_createorupdate_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_delete_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_get_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_list_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_listbyresourcegroup_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_update_autorest.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroup.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupproperties.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupupdate.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_wsfcdomainprofile.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/version.go diff --git a/internal/services/mssql/client/client.go b/internal/services/mssql/client/client.go index 38326bb63232..3cb15f82800f 100644 --- a/internal/services/mssql/client/client.go +++ b/internal/services/mssql/client/client.go @@ -5,6 +5,8 @@ package client import ( "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/v5.0/sql" // nolint: staticcheck + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" "github.com/hashicorp/terraform-provider-azurerm/internal/common" ) @@ -37,7 +39,9 @@ type Client struct { ServerVulnerabilityAssessmentsClient *sql.ServerVulnerabilityAssessmentsClient ServersClient *sql.ServersClient TransparentDataEncryptionsClient *sql.TransparentDataEncryptionsClient + VirtualMachinesAvailabilityGroupListenersClient *availabilitygrouplisteners.AvailabilityGroupListenersClient VirtualMachinesClient *sqlvirtualmachines.SqlVirtualMachinesClient + VirtualMachineGroupsClient *sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient VirtualNetworkRulesClient *sql.VirtualNetworkRulesClient } @@ -123,9 +127,15 @@ func NewClient(o *common.ClientOptions) *Client { transparentDataEncryptionsClient := sql.NewTransparentDataEncryptionsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&transparentDataEncryptionsClient.Client, o.ResourceManagerAuthorizer) + virtualMachinesAvailabilityGroupListenersClient := availabilitygrouplisteners.NewAvailabilityGroupListenersClientWithBaseURI(o.ResourceManagerEndpoint) + o.ConfigureClient(&virtualMachinesAvailabilityGroupListenersClient.Client, o.ResourceManagerAuthorizer) + virtualMachinesClient := sqlvirtualmachines.NewSqlVirtualMachinesClientWithBaseURI(o.ResourceManagerEndpoint) o.ConfigureClient(&virtualMachinesClient.Client, o.ResourceManagerAuthorizer) + virtualMachineGroupsClient := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupsClientWithBaseURI(o.ResourceManagerEndpoint) + o.ConfigureClient(&virtualMachineGroupsClient.Client, o.ResourceManagerAuthorizer) + virtualNetworkRulesClient := sql.NewVirtualNetworkRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&virtualNetworkRulesClient.Client, o.ResourceManagerAuthorizer) @@ -134,30 +144,32 @@ func NewClient(o *common.ClientOptions) *Client { DatabaseExtendedBlobAuditingPoliciesClient: &databaseExtendedBlobAuditingPoliciesClient, DatabaseSecurityAlertPoliciesClient: &databaseSecurityAlertPoliciesClient, DatabaseVulnerabilityAssessmentRuleBaselinesClient: &databaseVulnerabilityAssessmentRuleBaselinesClient, - DatabasesClient: &databasesClient, - ElasticPoolsClient: &elasticPoolsClient, - EncryptionProtectorClient: &encryptionProtectorClient, - FailoverGroupsClient: &failoverGroupsClient, - FirewallRulesClient: &firewallRulesClient, - GeoBackupPoliciesClient: &geoBackupPoliciesClient, - JobAgentsClient: &jobAgentsClient, - JobCredentialsClient: &jobCredentialsClient, - LongTermRetentionPoliciesClient: &longTermRetentionPoliciesClient, - OutboundFirewallRulesClient: &outboundFirewallRulesClient, - ReplicationLinksClient: &replicationLinksClient, - RestorableDroppedDatabasesClient: &restorableDroppedDatabasesClient, - ServerAzureADAdministratorsClient: &serverAzureADAdministratorsClient, - ServerAzureADOnlyAuthenticationsClient: &serverAzureADOnlyAuthenticationsClient, - ServerConnectionPoliciesClient: &serverConnectionPoliciesClient, - ServerDNSAliasClient: &serverDNSAliasClient, - ServerDevOpsAuditSettingsClient: &serverDevOpsAuditSettingsClient, - ServerExtendedBlobAuditingPoliciesClient: &serverExtendedBlobAuditingPoliciesClient, - ServerKeysClient: &serverKeysClient, - ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient, - ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient, - ServersClient: &serversClient, - TransparentDataEncryptionsClient: &transparentDataEncryptionsClient, - VirtualMachinesClient: &virtualMachinesClient, - VirtualNetworkRulesClient: &virtualNetworkRulesClient, + DatabasesClient: &databasesClient, + ElasticPoolsClient: &elasticPoolsClient, + EncryptionProtectorClient: &encryptionProtectorClient, + FailoverGroupsClient: &failoverGroupsClient, + FirewallRulesClient: &firewallRulesClient, + GeoBackupPoliciesClient: &geoBackupPoliciesClient, + JobAgentsClient: &jobAgentsClient, + JobCredentialsClient: &jobCredentialsClient, + LongTermRetentionPoliciesClient: &longTermRetentionPoliciesClient, + OutboundFirewallRulesClient: &outboundFirewallRulesClient, + ReplicationLinksClient: &replicationLinksClient, + RestorableDroppedDatabasesClient: &restorableDroppedDatabasesClient, + ServerAzureADAdministratorsClient: &serverAzureADAdministratorsClient, + ServerAzureADOnlyAuthenticationsClient: &serverAzureADOnlyAuthenticationsClient, + ServerConnectionPoliciesClient: &serverConnectionPoliciesClient, + ServerDNSAliasClient: &serverDNSAliasClient, + ServerDevOpsAuditSettingsClient: &serverDevOpsAuditSettingsClient, + ServerExtendedBlobAuditingPoliciesClient: &serverExtendedBlobAuditingPoliciesClient, + ServerKeysClient: &serverKeysClient, + ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient, + ServerVulnerabilityAssessmentsClient: &serverVulnerabilityAssessmentsClient, + ServersClient: &serversClient, + TransparentDataEncryptionsClient: &transparentDataEncryptionsClient, + VirtualMachinesAvailabilityGroupListenersClient: &virtualMachinesAvailabilityGroupListenersClient, + VirtualMachinesClient: &virtualMachinesClient, + VirtualMachineGroupsClient: &virtualMachineGroupsClient, + VirtualNetworkRulesClient: &virtualNetworkRulesClient, } } diff --git a/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go new file mode 100644 index 000000000000..b29fb596ebad --- /dev/null +++ b/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go @@ -0,0 +1,154 @@ +package helper + +import ( + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" + "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" + lbValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" + sqlValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate" + networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { + PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` + PublicIpAddressId string `tfschema:"public_ip_address_id"` + LoadBalancerId string `tfschema:"load_balancer_id"` + ProbePort int `tfschema:"probe_port"` + SqlVirtualMachineInstances []string `tfschema:"sql_virtual_machine_instances"` +} + +func LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "private_ip_address": PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + + "public_ip_address_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"load_balancer_configuration.0.private_ip_address"}, + ValidateFunc: networkValidate.PublicIpAddressID, + }, + + "load_balancer_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: lbValidate.LoadBalancerID, + }, + + "probe_port": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validate.PortNumber, + }, + + "sql_virtual_machine_instances": { + Type: pluginsdk.TypeSet, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, + }, + }, + }, + }, + } +} + +type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { + IpAddress string `tfschema:"ip_address"` + SubnetId string `tfschema:"subnet_id"` +} + +func PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Optional: true, + ForceNew: true, + MinItems: 1, + ConflictsWith: []string{"load_balancer_configuration.0.public_ip_address_id"}, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ip_address": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IsIPAddress, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, + }, + }, + } +} + +type ReplicaMsSqlVirtualMachineAvailabilityGroupListener struct { + SqlVirtualMachineInstanceId string `tfschema:"sql_virtual_machine_instance_id"` + Role string `tfschema:"role"` + Commit string `tfschema:"commit"` + Failover string `tfschema:"failover"` + ReadableSecondary string `tfschema:"readable_secondary"` +} + +func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeSet, + Optional: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "sql_virtual_machine_instance_id": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: sqlValidate.SqlVirtualMachineID, + DiffSuppressFunc: suppress.CaseDifference, + }, + + "role": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.RolePrimary), string(availabilitygrouplisteners.RoleSecondary)}, false), + }, + + "commit": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.CommitSynchronousCommit), string(availabilitygrouplisteners.CommitAsynchronousCommit)}, false), + }, + + "failover": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.FailoverManual), string(availabilitygrouplisteners.FailoverAutomatic)}, false), + }, + + "readable_secondary": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.ReadableSecondaryNo), string(availabilitygrouplisteners.ReadableSecondaryReadOnly), string(availabilitygrouplisteners.ReadableSecondaryAll)}, false), + }, + }, + }, + } +} diff --git a/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go new file mode 100644 index 000000000000..d60c54efe676 --- /dev/null +++ b/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go @@ -0,0 +1,95 @@ +package helper + +import ( + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type WsfcDomainProfile struct { + Fqdn string `tfschema:"fqdn"` + OuPath string `tfschema:"ou_path"` + ClusterBootstrapAccountName string `tfschema:"cluster_bootstrap_account_name"` + ClusterOperatorAccountName string `tfschema:"cluster_operator_account_name"` + SqlServiceAccountName string `tfschema:"sql_service_account_name"` + FileShareWitnessPath string `tfschema:"file_share_witness_path"` + StorageAccountUrl string `tfschema:"storage_account_url"` + StorageAccountPrimaryKey string `tfschema:"storage_account_primary_key"` + ClusterSubnetType string `tfschema:"cluster_subnet_type"` +} + +func WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeList, + Required: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "fqdn": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "ou_path": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "cluster_bootstrap_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "cluster_operator_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "sql_service_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "file_share_witness_path": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_account_url": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_account_primary_key": { + Type: pluginsdk.TypeString, + Optional: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "cluster_subnet_type": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sqlvirtualmachinegroups.ClusterSubnetTypeMultiSubnet), + string(sqlvirtualmachinegroups.ClusterSubnetTypeSingleSubnet), + }, false), + }, + }, + }, + } +} diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go new file mode 100644 index 000000000000..9b08be63f498 --- /dev/null +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go @@ -0,0 +1,482 @@ +package mssql + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + lbParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/helper" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/parse" + networkParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type MsSqlVirtualMachineAvailabilityGroupListenerResource struct{} + +type MsSqlVirtualMachineAvailabilityGroupListenerModel struct { + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + SqlVirtualMachineGroupName string `tfschema:"sql_virtual_machine_group_name"` + AvailabilityGroupName string `tfschema:"availability_group_name"` + + CreateDefaultAvailabilityGroup bool `tfschema:"create_default_availability_group"` + Port int `tfschema:"port"` + LoadBalancerConfiguration []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"load_balancer_configuration"` + Replica []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"replica"` +} + +var _ sdk.Resource = MsSqlVirtualMachineAvailabilityGroupListenerResource{} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) ModelObject() interface{} { + return &MsSqlVirtualMachineAvailabilityGroupListenerModel{} +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) ResourceType() string { + return "azurerm_mssql_virtual_machine_availability_group_listener" +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return availabilitygrouplisteners.ValidateAvailabilityGroupListenerID +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "sql_virtual_machine_group_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 15), + }, + + "availability_group_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + }, + + "create_default_availability_group": { + Type: pluginsdk.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + + "port": { + Type: pluginsdk.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validate.PortNumber, + }, + + "load_balancer_configuration": helper.LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + + "replica": helper.ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + } +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Attributes() map[string]*schema.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model MsSqlVirtualMachineAvailabilityGroupListenerModel + if err := metadata.Decode(&model); err != nil { + return err + } + + client := metadata.Client.MSSQL.VirtualMachinesAvailabilityGroupListenersClient + subscriptionId := metadata.Client.Account.SubscriptionId + + id := availabilitygrouplisteners.NewAvailabilityGroupListenerID(subscriptionId, model.ResourceGroup, model.SqlVirtualMachineGroupName, model.Name) + + existing, err := client.Get(ctx, id, availabilitygrouplisteners.GetOperationOptions{Expand: utils.String("AvailabilityGroupConfiguration")}) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + lbConfigs, err := expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(model.LoadBalancerConfiguration) + if err != nil { + return err + } + + replicas, err := expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(model.Replica) + if err != nil { + return err + } + + parameters := availabilitygrouplisteners.AvailabilityGroupListener{ + Properties: &availabilitygrouplisteners.AvailabilityGroupListenerProperties{ + AvailabilityGroupName: utils.String(model.AvailabilityGroupName), + LoadBalancerConfigurations: lbConfigs, + CreateDefaultAvailabilityGroupIfNotExist: utils.Bool(model.CreateDefaultAvailabilityGroup), + Port: utils.Int64(int64(model.Port)), + AvailabilityGroupConfiguration: &availabilitygrouplisteners.AgConfiguration{ + Replicas: replicas, + }, + }, + } + + if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + + client := metadata.Client.MSSQL.VirtualMachinesAvailabilityGroupListenersClient + + id, err := availabilitygrouplisteners.ParseAvailabilityGroupListenerID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id, availabilitygrouplisteners.GetOperationOptions{Expand: utils.String("AvailabilityGroupConfiguration")}) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + return fmt.Errorf("reading %s: %+v", *id, err) + } + + state := MsSqlVirtualMachineAvailabilityGroupListenerModel{ + Name: id.AvailabilityGroupListenerName, + ResourceGroup: id.ResourceGroupName, + SqlVirtualMachineGroupName: id.SqlVirtualMachineGroupName, + } + + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + + avGroupName := "" + if props.AvailabilityGroupName != nil { + avGroupName = *props.AvailabilityGroupName + } + state.AvailabilityGroupName = avGroupName + + createDefaultAvailabilityGroup := true + if props.CreateDefaultAvailabilityGroupIfNotExist != nil { + createDefaultAvailabilityGroup = *props.CreateDefaultAvailabilityGroupIfNotExist + } + state.CreateDefaultAvailabilityGroup = createDefaultAvailabilityGroup + + var port int64 + if props.Port != nil { + port = *props.Port + } + state.Port = int(port) + + avGroupListenerLbConfigs, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(props.LoadBalancerConfigurations, id.SubscriptionId) + if err != nil { + return fmt.Errorf("setting `load_balancer_configuration`: %+v", err) + } + state.LoadBalancerConfiguration = avGroupListenerLbConfigs + + if props.AvailabilityGroupConfiguration != nil { + if props.AvailabilityGroupConfiguration.Replicas != nil { + + replicas, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(props.AvailabilityGroupConfiguration.Replicas) + if err != nil { + return fmt.Errorf("setting `replica`: %+v", err) + } + state.Replica = replicas + } + } + } + } + return metadata.Encode(&state) + }, + } +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.MSSQL.VirtualMachinesAvailabilityGroupListenersClient + + id, err := availabilitygrouplisteners.ParseAvailabilityGroupListenerID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err = client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} + +func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(lbConfigs []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.LoadBalancerConfiguration, error) { + results := make([]availabilitygrouplisteners.LoadBalancerConfiguration, 0) + + for _, lb := range lbConfigs { + + lbConfig := availabilitygrouplisteners.LoadBalancerConfiguration{ + ProbePort: utils.Int64(int64(lb.ProbePort)), + } + + parsedLbId := "" + if lb.LoadBalancerId != "" { + id, err := lbParse.LoadBalancerID(lb.LoadBalancerId) + if err != nil { + return nil, err + } + parsedLbId = id.ID() + } + lbConfig.LoadBalancerResourceId = utils.String(parsedLbId) + + var parsedIds []interface{} + for _, sqlVmId := range lb.SqlVirtualMachineInstances { + parsedId, err := parse.SqlVirtualMachineID(sqlVmId) + if err != nil { + return nil, err + } + parsedIds = append(parsedIds, parsedId.ID()) + } + lbConfig.SqlVirtualMachineInstances = utils.ExpandStringSlice(parsedIds) + + if lb.PrivateIpAddress != nil { + privateIpAddress, err := expandMsSqlVirtualMachinePrivateIpAddress(lb.PrivateIpAddress) + if err != nil { + return nil, err + } + lbConfig.PrivateIPAddress = privateIpAddress + } + + if publicIp := lb.PublicIpAddressId; publicIp != "" { + id, err := networkParse.PublicIpAddressID(publicIp) + if err != nil { + return nil, err + } + lbConfig.PublicIPAddressResourceId = utils.String(id.ID()) + } + results = append(results, lbConfig) + } + return &results, nil +} + +func expandMsSqlVirtualMachinePrivateIpAddress(input []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener) (*availabilitygrouplisteners.PrivateIPAddress, error) { + if len(input) == 0 { + return nil, nil + } + + var ipAddress, subnetId string + if input[0].IpAddress != "" { + ipAddress = input[0].IpAddress + } + + if input[0].SubnetId != "" { + id, err := networkParse.SubnetID(input[0].SubnetId) + if err != nil { + return nil, err + } + subnetId = id.ID() + } + + return &availabilitygrouplisteners.PrivateIPAddress{ + IPAddress: utils.String(ipAddress), + + SubnetResourceId: utils.String(subnetId), + }, nil +} + +func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(input *[]availabilitygrouplisteners.LoadBalancerConfiguration, subscriptionId string) ([]helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) + if input == nil || len(*input) == 0 { + return results, nil + } + + for _, lbConfig := range *input { + + var privateIpAddress []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener + if lbConfig.PrivateIPAddress != nil { + flattenedPrivateIp, err := flattenPrivateIpAddress(*lbConfig.PrivateIPAddress) + if err != nil { + return nil, err + } + privateIpAddress = flattenedPrivateIp + } + + publicIpAddressId := "" + if lbConfig.PublicIPAddressResourceId != nil { + publicIpAddressId = *lbConfig.PublicIPAddressResourceId + } + + loadBalancerId := "" + if lbConfig.LoadBalancerResourceId != nil { + id, err := lbParse.LoadBalancerID(*lbConfig.LoadBalancerResourceId) + if err != nil { + return nil, err + } + loadBalancerId = id.ID() + } + + var probePort int64 + if lbConfig.ProbePort != nil { + probePort = *lbConfig.ProbePort + } + + var sqlVirtualMachineIds []string + if lbConfig.SqlVirtualMachineInstances != nil { + sqlVirtualMachineIds = *lbConfig.SqlVirtualMachineInstances + var parsedIds []string + for _, sqlVmId := range sqlVirtualMachineIds { + parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineID(sqlVmId) + // get correct casing for subscription in id + newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) + if err != nil { + return nil, err + } + parsedIds = append(parsedIds, newId.ID()) + } + sqlVirtualMachineIds = parsedIds + } + + v := helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ + PrivateIpAddress: privateIpAddress, + PublicIpAddressId: publicIpAddressId, + LoadBalancerId: loadBalancerId, + ProbePort: int(probePort), + SqlVirtualMachineInstances: sqlVirtualMachineIds, + } + + results = append(results, v) + } + return results, nil +} + +func flattenPrivateIpAddress(input availabilitygrouplisteners.PrivateIPAddress) ([]helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener, error) { + + privateIpAddress := helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{} + + ipAddress := "" + if input.IPAddress != nil { + ipAddress = *input.IPAddress + } + privateIpAddress.IpAddress = ipAddress + + subnetId := "" + if input.SubnetResourceId != nil { + id, err := networkParse.SubnetID(*input.SubnetResourceId) + if err != nil { + return nil, err + } + subnetId = id.ID() + } + + privateIpAddress.SubnetId = subnetId + + return []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{privateIpAddress}, nil +} + +func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.AgReplica, error) { + results := make([]availabilitygrouplisteners.AgReplica, 0) + + for _, rep := range replicas { + + role := availabilitygrouplisteners.Role(rep.Role) + commit := availabilitygrouplisteners.Commit(rep.Commit) + failover := availabilitygrouplisteners.Failover(rep.Failover) + readableSecondary := availabilitygrouplisteners.ReadableSecondary(rep.ReadableSecondary) + + replica := availabilitygrouplisteners.AgReplica{ + Role: &role, + Commit: &commit, + Failover: &failover, + ReadableSecondary: &readableSecondary, + } + + sqlVirtualMachineId := rep.SqlVirtualMachineInstanceId + if sqlVirtualMachineId != "" { + id, err := sqlvirtualmachines.ParseSqlVirtualMachineID(sqlVirtualMachineId) + if err != nil { + return nil, err + } + sqlVirtualMachineId = id.ID() + } + replica.SqlVirtualMachineInstanceId = utils.String(sqlVirtualMachineId) + + results = append(results, replica) + } + return &results, nil +} + +func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availabilitygrouplisteners.AgReplica) ([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, 0) + if input == nil || len(*input) == 0 { + return results, nil + } + + for _, replica := range *input { + + sqlVirtualMachineInstanceId := "" + if replica.SqlVirtualMachineInstanceId != nil { + parsedSqlVmId, err := sqlvirtualmachines.ParseSqlVirtualMachineID(*replica.SqlVirtualMachineInstanceId) + if err != nil { + return nil, err + } + + sqlVirtualMachineInstanceId = parsedSqlVmId.ID() + } + + v := helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener{ + SqlVirtualMachineInstanceId: sqlVirtualMachineInstanceId, + } + + if replica.Role != nil { + v.Role = string(*replica.Role) + } + + if replica.Commit != nil { + v.Commit = string(*replica.Commit) + } + + if replica.Failover != nil { + v.Failover = string(*replica.Failover) + } + + if replica.ReadableSecondary != nil { + v.ReadableSecondary = string(*replica.ReadableSecondary) + } + + results = append(results, v) + } + return results, nil +} diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go new file mode 100644 index 000000000000..5050edde914d --- /dev/null +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go @@ -0,0 +1,82 @@ +package mssql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type MsSqlVirtualMachineAvailabilityGroupListenerResource struct{} + +func TestAccMsSqlVirtualMachineAvailabilityGroupListenerResource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_availability_group_listener", "test") + r := MsSqlVirtualMachineAvailabilityGroupListenerResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + }) +} + +func (MsSqlVirtualMachineAvailabilityGroupListenerResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + + id, err := availabilitygrouplisteners.ParseAvailabilityGroupListenerID(state.ID) + if err != nil { + return nil, err + } + + resp, err := client.MSSQL.VirtualMachinesAvailabilityGroupListenersClient.Get(ctx, *id, availabilitygrouplisteners.GetOperationOptions{Expand: utils.String("*")}) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return nil, fmt.Errorf("%s does not exist", *id) + } + return nil, fmt.Errorf("reading %s: %v", *id, err) + } + return utils.Bool(resp.Model != nil), nil +} + +// TODO add proper test +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) basic() string { + return fmt.Sprintf(` +resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { + name = "MyListener" + resource_group_name = // *** resource_group_name + availability_group_name = "default2" + port = 1432 + create_default_availability_group = true + sql_virtual_machine_group_name = // *** sql_virtual_machine_group_name + + + load_balancer_configuration { + private_ip_address { + ip_address = "10.0.2.8" + subnet_id = + } + + load_balancer_id = // *** load_balancer_id + probe_port = 51572 + sql_virtual_machine_instances = [ // *** sql_virtual_machine_instances ] + } + + replica { + sql_virtual_machine_instance_id = // *** sql_virtual_machine_instance_id + role = "PRIMARY" + commit = "SYNCHRONOUS_COMMIT" + failover = "AUTOMATIC" + readable_secondary = "ALL" + } +} +`) +} diff --git a/internal/services/mssql/mssql_virtual_machine_group_resource.go b/internal/services/mssql/mssql_virtual_machine_group_resource.go new file mode 100644 index 000000000000..45e49f9d256f --- /dev/null +++ b/internal/services/mssql/mssql_virtual_machine_group_resource.go @@ -0,0 +1,340 @@ +package mssql + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/helper" + "github.com/hashicorp/terraform-provider-azurerm/internal/tags" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type MsSqlVirtualMachineGroupResource struct{} + +type MsSqlVirtualMachineGroupModel struct { + Name string `tfschema:"name"` + ResourceGroup string `tfschema:"resource_group_name"` + Location string `tfschema:"location"` + + SqlImageOffer string `tfschema:"sql_image_offer"` + SqlImageSku string `tfschema:"sql_image_sku"` + WsfcDomainProfile []helper.WsfcDomainProfile `tfschema:"wsfc_domain_profile"` + Tags map[string]string `tfschema:"tags"` +} + +var _ sdk.Resource = MsSqlVirtualMachineGroupResource{} +var _ sdk.ResourceWithUpdate = MsSqlVirtualMachineGroupResource{} + +func (r MsSqlVirtualMachineGroupResource) ModelObject() interface{} { + return &MsSqlVirtualMachineGroupModel{} +} + +func (r MsSqlVirtualMachineGroupResource) ResourceType() string { + return "azurerm_mssql_virtual_machine_group" +} + +func (r MsSqlVirtualMachineGroupResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return availabilitygrouplisteners.ValidateSqlVirtualMachineGroupID +} + +func (r MsSqlVirtualMachineGroupResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 15), + }, + + "resource_group_name": commonschema.ResourceGroupName(), + + "location": commonschema.Location(), + + "sql_image_offer": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "SQL2016-WS2016", + "SQL2017-WS2016", + "SQL2019-WS2019", + }, false), + }, + + "sql_image_sku": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sqlvirtualmachinegroups.SqlVmGroupImageSkuDeveloper), + string(sqlvirtualmachinegroups.SqlVmGroupImageSkuEnterprise), + }, false), + }, + + "wsfc_domain_profile": helper.WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup(), + + "tags": tags.Schema(), + } +} + +func (r MsSqlVirtualMachineGroupResource) Attributes() map[string]*schema.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r MsSqlVirtualMachineGroupResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model MsSqlVirtualMachineGroupModel + if err := metadata.Decode(&model); err != nil { + return err + } + + client := metadata.Client.MSSQL.VirtualMachineGroupsClient + subscriptionId := metadata.Client.Account.SubscriptionId + + id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID(subscriptionId, model.ResourceGroup, model.Name) + + existing, err := client.Get(ctx, id) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for present of existing %s: %+v", id, err) + } + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + sqlVmGroupImageSku := sqlvirtualmachinegroups.SqlVmGroupImageSku(model.SqlImageSku) + + parameters := sqlvirtualmachinegroups.SqlVirtualMachineGroup{ + Properties: &sqlvirtualmachinegroups.SqlVirtualMachineGroupProperties{ + SqlImageOffer: utils.String(model.SqlImageOffer), + SqlImageSku: &sqlVmGroupImageSku, + WsfcDomainProfile: expandMsSqlVirtualMachineGroupWsfcDomainProfile(model.WsfcDomainProfile), + }, + + Location: azure.NormalizeLocation(model.Location), + Tags: &model.Tags, + } + + parameters.Properties.WsfcDomainProfile.FileShareWitnessPath = utils.String("") + + if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r MsSqlVirtualMachineGroupResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + + client := metadata.Client.MSSQL.VirtualMachineGroupsClient + + id, err := sqlvirtualmachinegroups.ParseSqlVirtualMachineGroupID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + return fmt.Errorf("reading %s: %+v", *id, err) + } + + state := MsSqlVirtualMachineGroupModel{ + Name: id.SqlVirtualMachineGroupName, + ResourceGroup: id.ResourceGroupName, + } + + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + + sqlImageOffer := "" + if props.SqlImageOffer != nil { + sqlImageOffer = *props.SqlImageOffer + } + state.SqlImageOffer = sqlImageOffer + + sqlImageSku := "" + if props.SqlImageSku != nil { + sqlImageSku = string(*props.SqlImageSku) + } + state.SqlImageSku = sqlImageSku + + state.WsfcDomainProfile = flattenMsSqlVirtualMachineGroupWsfcDomainProfile(props.WsfcDomainProfile) + + } + state.Location = azure.NormalizeLocation(model.Location) + + if model.Tags != nil { + state.Tags = *model.Tags + } + } + return metadata.Encode(&state) + }, + } +} + +func (r MsSqlVirtualMachineGroupResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model MsSqlVirtualMachineGroupModel + if err := metadata.Decode(&model); err != nil { + return err + } + + client := metadata.Client.MSSQL.VirtualMachineGroupsClient + subscriptionId := metadata.Client.Account.SubscriptionId + + id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID(subscriptionId, model.ResourceGroup, model.Name) + + existing, err := client.Get(ctx, id) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for present of existing %s: %+v", id, err) + } + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + sqlVmGroupImageSku := sqlvirtualmachinegroups.SqlVmGroupImageSku(model.SqlImageSku) + + parameters := sqlvirtualmachinegroups.SqlVirtualMachineGroup{ + Properties: &sqlvirtualmachinegroups.SqlVirtualMachineGroupProperties{ + SqlImageOffer: utils.String(model.SqlImageOffer), + SqlImageSku: &sqlVmGroupImageSku, + WsfcDomainProfile: expandMsSqlVirtualMachineGroupWsfcDomainProfile(model.WsfcDomainProfile), + }, + + Location: azure.NormalizeLocation(model.Location), + Tags: &model.Tags, + } + + if err := client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + return nil + }, + } +} + +func (r MsSqlVirtualMachineGroupResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.MSSQL.VirtualMachineGroupsClient + + id, err := sqlvirtualmachinegroups.ParseSqlVirtualMachineGroupID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err = client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + return nil + }, + } +} + +func expandMsSqlVirtualMachineGroupWsfcDomainProfile(wsfcDomainProfile []helper.WsfcDomainProfile) *sqlvirtualmachinegroups.WsfcDomainProfile { + if wsfcDomainProfile == nil { + return nil + } + + result := sqlvirtualmachinegroups.WsfcDomainProfile{ + DomainFqdn: &wsfcDomainProfile[0].Fqdn, + OuPath: &wsfcDomainProfile[0].OuPath, + ClusterBootstrapAccount: &wsfcDomainProfile[0].ClusterBootstrapAccountName, + ClusterOperatorAccount: &wsfcDomainProfile[0].ClusterOperatorAccountName, + SqlServiceAccount: &wsfcDomainProfile[0].SqlServiceAccountName, + FileShareWitnessPath: &wsfcDomainProfile[0].FileShareWitnessPath, + StorageAccountUrl: &wsfcDomainProfile[0].StorageAccountUrl, + StorageAccountPrimaryKey: &wsfcDomainProfile[0].StorageAccountPrimaryKey, + } + + clusterSubnetType := sqlvirtualmachinegroups.ClusterSubnetType(wsfcDomainProfile[0].ClusterSubnetType) + result.ClusterSubnetType = &clusterSubnetType + + return &result +} + +func flattenMsSqlVirtualMachineGroupWsfcDomainProfile(domainProfile *sqlvirtualmachinegroups.WsfcDomainProfile) []helper.WsfcDomainProfile { + if domainProfile == nil { + return []helper.WsfcDomainProfile{} + } + + var fqdn string + if domainProfile.DomainFqdn != nil { + fqdn = *domainProfile.DomainFqdn + } + + var clusterOperatorAccountName string + if domainProfile.ClusterOperatorAccount != nil { + clusterOperatorAccountName = *domainProfile.ClusterOperatorAccount + } + + var clusterBootstrapAccountName string + if domainProfile.ClusterBootstrapAccount != nil { + clusterBootstrapAccountName = *domainProfile.ClusterBootstrapAccount + } + + var ouPath string + if domainProfile.OuPath != nil { + ouPath = *domainProfile.OuPath + } + + var sqlServiceAccountName string + if domainProfile.SqlServiceAccount != nil { + sqlServiceAccountName = *domainProfile.SqlServiceAccount + } + + var fileShareWitnessPath string + if domainProfile.FileShareWitnessPath != nil { + fileShareWitnessPath = *domainProfile.FileShareWitnessPath + } + + var storageAccountURL string + if domainProfile.StorageAccountUrl != nil { + storageAccountURL = *domainProfile.StorageAccountUrl + } + + var clusterSubnetType string + if domainProfile.ClusterSubnetType != nil { + clusterSubnetType = string(*domainProfile.ClusterSubnetType) + } + + return []helper.WsfcDomainProfile{ + { + Fqdn: fqdn, + OuPath: ouPath, + ClusterBootstrapAccountName: clusterBootstrapAccountName, + ClusterOperatorAccountName: clusterOperatorAccountName, + SqlServiceAccountName: sqlServiceAccountName, + FileShareWitnessPath: fileShareWitnessPath, + StorageAccountUrl: storageAccountURL, + ClusterSubnetType: clusterSubnetType, + }, + } +} diff --git a/internal/services/mssql/mssql_virtual_machine_group_resource_test.go b/internal/services/mssql/mssql_virtual_machine_group_resource_test.go new file mode 100644 index 000000000000..3fbb65a30a73 --- /dev/null +++ b/internal/services/mssql/mssql_virtual_machine_group_resource_test.go @@ -0,0 +1,165 @@ +package mssql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type MsSqlVirtualMachineGroupResource struct{} + +func TestAccMsSqlVirtualMachineGroupResource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_group", "test") + r := MsSqlVirtualMachineGroupResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + }) +} + +func TestAccMsSqlVirtualMachineGroup_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_group", "test") + r := MsSqlVirtualMachineGroupResource{} + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccMsSqlVirtualMachineGroupResource_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_group", "test") + r := MsSqlVirtualMachineGroupResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.complete(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (MsSqlVirtualMachineGroupResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := sqlvirtualmachinegroups.ParseSqlVirtualMachineGroupID(state.ID) + if err != nil { + return nil, err + } + + resp, err := client.MSSQL.VirtualMachineGroupsClient.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return nil, fmt.Errorf("%s does not exist", *id) + } + return nil, fmt.Errorf("reading %s: %v", *id, err) + } + return utils.Bool(resp.Model != nil), nil +} + +func (r MsSqlVirtualMachineGroupResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-mssql-%[1]d" + location = "%[2]s" +} + +resource "azurerm_mssql_virtual_machine_group" "test" { + name = "acctestag%[3]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + sql_image_offer = "SQL2017-WS2016" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = "testdomain.com" + cluster_subnet_type = "SingleSubnet" + } +} + + + + +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + +func (r MsSqlVirtualMachineGroupResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +resource "azurerm_mssql_virtual_machine_group" "import" { + name = azurerm_mssql_virtual_machine_group.test.name + resource_group_name = azurerm_mssql_virtual_machine_group.test.resource_group_name + location = azurerm_mssql_virtual_machine_group.test.location + + sql_image_offer = "SQL2017-WS2016" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = "testdomain.com" + cluster_subnet_type = "SingleSubnet" + } +} +`, r.basic(data)) +} + +func (r MsSqlVirtualMachineGroupResource) complete(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-mssql-%[1]d" + location = "%[2]s" +} + +resource "azurerm_storage_account" "test" { + name = "unlikely23exst2acct%[3]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_mssql_virtual_machine_group" "test" { + name = "acctestag%[4]s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + sql_image_offer = "SQL2017-WS2016" + sql_image_sku = "Developer" + + + wsfc_domain_profile { + fqdn = "testdomain.com" + cluster_bootstrap_account_name = "bootstrapacc%[5]s" + cluster_operator_account_name = "opacc%[5]s" + sql_service_account_name = "sqlsrvacc%[5]s" + storage_account_url = azurerm_storage_account.test.primary_blob_endpoint + cluster_subnet_type = "SingleSubnet" + } + + tags = { + test = "testing" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, data.RandomString) +} diff --git a/internal/services/mssql/mssql_virtual_machine_resource.go b/internal/services/mssql/mssql_virtual_machine_resource.go index 6c99afdfa861..819965c2837a 100644 --- a/internal/services/mssql/mssql_virtual_machine_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_resource.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" @@ -431,6 +432,40 @@ func resourceMsSqlVirtualMachine() *pluginsdk.Resource { }, }, + "sql_virtual_machine_group_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: sqlvirtualmachinegroups.ValidateSqlVirtualMachineGroupID, + }, + + "wsfc_domain_credentials": { + Type: pluginsdk.TypeList, + Optional: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "cluster_bootstrap_account_password": { + Type: pluginsdk.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "cluster_operator_account_password": { + Type: pluginsdk.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "sql_service_account_password": { + Type: pluginsdk.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + "tags": commonschema.Tags(), }, } @@ -491,6 +526,14 @@ func resourceMsSqlVirtualMachineCreateUpdate(d *pluginsdk.ResourceData, meta int if *respvm.Location == "" { return fmt.Errorf("location is empty from making Read request on Azure Virtual Machine %s: %+v", id.SqlVirtualMachineName, err) } + sqlVmGroupId := "" + if sqlVmGroupId = d.Get("sql_virtual_machine_group_id").(string); sqlVmGroupId != "" { + parsedVmGroupId, err := sqlvirtualmachines.ParseSqlVirtualMachineGroupIDInsensitively(sqlVmGroupId) + if err != nil { + return err + } + sqlVmGroupId = parsedVmGroupId.ID() + } sqlInstance, err := expandSqlVirtualMachineSQLInstance(d.Get("sql_instance").([]interface{})) if err != nil { @@ -508,10 +551,12 @@ func resourceMsSqlVirtualMachineCreateUpdate(d *pluginsdk.ResourceData, meta int parameters := sqlvirtualmachines.SqlVirtualMachine{ Location: *respvm.Location, Properties: &sqlvirtualmachines.SqlVirtualMachineProperties{ - AutoBackupSettings: autoBackupSettings, - AutoPatchingSettings: expandSqlVirtualMachineAutoPatchingSettings(d.Get("auto_patching").([]interface{})), - AssessmentSettings: expandSqlVirtualMachineAssessmentSettings(d.Get("assessment").([]interface{})), - KeyVaultCredentialSettings: expandSqlVirtualMachineKeyVaultCredential(d.Get("key_vault_credential").([]interface{})), + AutoBackupSettings: autoBackupSettings, + AutoPatchingSettings: expandSqlVirtualMachineAutoPatchingSettings(d.Get("auto_patching").([]interface{})), + AssessmentSettings: expandSqlVirtualMachineAssessmentSettings(d.Get("assessment").([]interface{})), + KeyVaultCredentialSettings: expandSqlVirtualMachineKeyVaultCredential(d.Get("key_vault_credential").([]interface{})), + WsfcDomainCredentials: expandSqlVirtualMachineWsfcDomainCredentials(d.Get("wsfc_domain_credentials").([]interface{})), + SqlVirtualMachineGroupResourceId: utils.String(sqlVmGroupId), ServerConfigurationsManagementSettings: &sqlvirtualmachines.ServerConfigurationsManagementSettings{ AdditionalFeaturesServerConfigurations: &sqlvirtualmachines.AdditionalFeaturesServerConfigurations{ IsRServicesEnabled: utils.Bool(d.Get("r_services_enabled").(bool)), @@ -637,7 +682,7 @@ func resourceMsSqlVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} } if scus := mgmtSettings.SqlConnectivityUpdateSettings; scus != nil { d.Set("sql_connectivity_port", mgmtSettings.SqlConnectivityUpdateSettings.Port) - d.Set("sql_connectivity_type", string(pointer.From(mgmtSettings.SqlConnectivityUpdateSettings.ConnectivityType))) + d.Set("sql_connectivity_type", pointer.From(mgmtSettings.SqlConnectivityUpdateSettings.ConnectivityType)) } d.Set("sql_instance", flattenSqlVirtualMachineSQLInstance(mgmtSettings.SqlInstanceSettings)) @@ -653,6 +698,21 @@ func resourceMsSqlVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} if err := d.Set("storage_configuration", flattenSqlVirtualMachineStorageConfigurationSettings(props.StorageConfigurationSettings, storageWorkloadType)); err != nil { return fmt.Errorf("setting `storage_configuration`: %+v", err) } + + if err := d.Set("wsfc_domain_credentials", flattenSqlVirtualMachineWsfcDomainCredentials(props.WsfcDomainCredentials)); err != nil { + return fmt.Errorf("setting `wsfc_domain_credentials`: %+v", err) + } + + sqlVirtualMachineGroupIdStr := "" + if props.SqlVirtualMachineGroupResourceId != nil { + sqlVirtualMachineGroupId, err := sqlvirtualmachines.ParseSqlVirtualMachineGroupIDInsensitively(*props.SqlVirtualMachineGroupResourceId) + if err != nil { + return err + } + sqlVirtualMachineGroupIdStr = sqlVirtualMachineGroupId.ID() + } + d.Set("sql_virtual_machine_group_id", sqlVirtualMachineGroupIdStr) + if err := tags.FlattenAndSet(d, model.Tags); err != nil { return err } @@ -1380,3 +1440,45 @@ func flattenSqlVirtualMachineSQLInstance(input *sqlvirtualmachines.SQLInstanceSe }, } } + +func expandSqlVirtualMachineWsfcDomainCredentials(input []interface{}) *sqlvirtualmachines.WsfcDomainCredentials { + if len(input) == 0 { + return nil + } + wsfcDomainCredentials := input[0].(map[string]interface{}) + + return &sqlvirtualmachines.WsfcDomainCredentials{ + ClusterBootstrapAccountPassword: utils.String(wsfcDomainCredentials["cluster_bootstrap_account_password"].(string)), + ClusterOperatorAccountPassword: utils.String(wsfcDomainCredentials["cluster_operator_account_password"].(string)), + SqlServiceAccountPassword: utils.String(wsfcDomainCredentials["sql_service_account_password"].(string)), + } +} + +func flattenSqlVirtualMachineWsfcDomainCredentials(wsfcDomainCredentials *sqlvirtualmachines.WsfcDomainCredentials) []interface{} { + if wsfcDomainCredentials == nil { + return []interface{}{} + } + + clusterBootstrapAccountPassword := "" + if wsfcDomainCredentials.ClusterBootstrapAccountPassword != nil { + clusterBootstrapAccountPassword = *wsfcDomainCredentials.ClusterBootstrapAccountPassword + } + + clusterOperatorAccountPassword := "" + if wsfcDomainCredentials.ClusterOperatorAccountPassword != nil { + clusterOperatorAccountPassword = *wsfcDomainCredentials.ClusterOperatorAccountPassword + } + + sqlServiceAccountPassword := "" + if wsfcDomainCredentials.SqlServiceAccountPassword != nil { + sqlServiceAccountPassword = *wsfcDomainCredentials.SqlServiceAccountPassword + } + + return []interface{}{ + map[string]interface{}{ + "cluster_bootstrap_account_password": clusterBootstrapAccountPassword, + "cluster_operator_account_password": clusterOperatorAccountPassword, + "sql_service_account_password": sqlServiceAccountPassword, + }, + } +} diff --git a/internal/services/mssql/registration.go b/internal/services/mssql/registration.go index 69c9cf148d64..ac1e8af1f096 100644 --- a/internal/services/mssql/registration.go +++ b/internal/services/mssql/registration.go @@ -71,6 +71,8 @@ func (r Registration) DataSources() []sdk.DataSource { func (r Registration) Resources() []sdk.Resource { return []sdk.Resource{ MsSqlFailoverGroupResource{}, + MsSqlVirtualMachineAvailabilityGroupListenerResource{}, + MsSqlVirtualMachineGroupResource{}, ServerDNSAliasResource{}, } } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/README.md new file mode 100644 index 000000000000..85aca2fdb1c1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/README.md @@ -0,0 +1,82 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners` Documentation + +The `availabilitygrouplisteners` SDK allows for interaction with the Azure Resource Manager Service `sqlvirtualmachine` (API Version `2022-02-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" +``` + + +### Client Initialization + +```go +client := availabilitygrouplisteners.NewAvailabilityGroupListenersClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `AvailabilityGroupListenersClient.CreateOrUpdate` + +```go +ctx := context.TODO() +id := availabilitygrouplisteners.NewAvailabilityGroupListenerID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue", "availabilityGroupListenerValue") + +payload := availabilitygrouplisteners.AvailabilityGroupListener{ + // ... +} + + +if err := client.CreateOrUpdateThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` + + +### Example Usage: `AvailabilityGroupListenersClient.Delete` + +```go +ctx := context.TODO() +id := availabilitygrouplisteners.NewAvailabilityGroupListenerID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue", "availabilityGroupListenerValue") + +if err := client.DeleteThenPoll(ctx, id); err != nil { + // handle the error +} +``` + + +### Example Usage: `AvailabilityGroupListenersClient.Get` + +```go +ctx := context.TODO() +id := availabilitygrouplisteners.NewAvailabilityGroupListenerID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue", "availabilityGroupListenerValue") + +read, err := client.Get(ctx, id, availabilitygrouplisteners.DefaultGetOperationOptions()) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `AvailabilityGroupListenersClient.ListByGroup` + +```go +ctx := context.TODO() +id := availabilitygrouplisteners.NewSqlVirtualMachineGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue") + +// alternatively `client.ListByGroup(ctx, id)` can be used to do batched pagination +items, err := client.ListByGroupComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/client.go new file mode 100644 index 000000000000..5bfcd62f8b65 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/client.go @@ -0,0 +1,18 @@ +package availabilitygrouplisteners + +import "github.com/Azure/go-autorest/autorest" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AvailabilityGroupListenersClient struct { + Client autorest.Client + baseUri string +} + +func NewAvailabilityGroupListenersClientWithBaseURI(endpoint string) AvailabilityGroupListenersClient { + return AvailabilityGroupListenersClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/constants.go new file mode 100644 index 000000000000..7e0f67d0f488 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/constants.go @@ -0,0 +1,121 @@ +package availabilitygrouplisteners + +import "strings" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type Commit string + +const ( + CommitAsynchronousCommit Commit = "Asynchronous_Commit" + CommitSynchronousCommit Commit = "Synchronous_Commit" +) + +func PossibleValuesForCommit() []string { + return []string{ + string(CommitAsynchronousCommit), + string(CommitSynchronousCommit), + } +} + +func parseCommit(input string) (*Commit, error) { + vals := map[string]Commit{ + "asynchronous_commit": CommitAsynchronousCommit, + "synchronous_commit": CommitSynchronousCommit, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := Commit(input) + return &out, nil +} + +type Failover string + +const ( + FailoverAutomatic Failover = "Automatic" + FailoverManual Failover = "Manual" +) + +func PossibleValuesForFailover() []string { + return []string{ + string(FailoverAutomatic), + string(FailoverManual), + } +} + +func parseFailover(input string) (*Failover, error) { + vals := map[string]Failover{ + "automatic": FailoverAutomatic, + "manual": FailoverManual, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := Failover(input) + return &out, nil +} + +type ReadableSecondary string + +const ( + ReadableSecondaryAll ReadableSecondary = "All" + ReadableSecondaryNo ReadableSecondary = "No" + ReadableSecondaryReadOnly ReadableSecondary = "Read_Only" +) + +func PossibleValuesForReadableSecondary() []string { + return []string{ + string(ReadableSecondaryAll), + string(ReadableSecondaryNo), + string(ReadableSecondaryReadOnly), + } +} + +func parseReadableSecondary(input string) (*ReadableSecondary, error) { + vals := map[string]ReadableSecondary{ + "all": ReadableSecondaryAll, + "no": ReadableSecondaryNo, + "read_only": ReadableSecondaryReadOnly, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ReadableSecondary(input) + return &out, nil +} + +type Role string + +const ( + RolePrimary Role = "Primary" + RoleSecondary Role = "Secondary" +) + +func PossibleValuesForRole() []string { + return []string{ + string(RolePrimary), + string(RoleSecondary), + } +} + +func parseRole(input string) (*Role, error) { + vals := map[string]Role{ + "primary": RolePrimary, + "secondary": RoleSecondary, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := Role(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go new file mode 100644 index 000000000000..8f483e83d298 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go @@ -0,0 +1,140 @@ +package availabilitygrouplisteners + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +var _ resourceids.ResourceId = AvailabilityGroupListenerId{} + +// AvailabilityGroupListenerId is a struct representing the Resource ID for a Availability Group Listener +type AvailabilityGroupListenerId struct { + SubscriptionId string + ResourceGroupName string + SqlVirtualMachineGroupName string + AvailabilityGroupListenerName string +} + +// NewAvailabilityGroupListenerID returns a new AvailabilityGroupListenerId struct +func NewAvailabilityGroupListenerID(subscriptionId string, resourceGroupName string, sqlVirtualMachineGroupName string, availabilityGroupListenerName string) AvailabilityGroupListenerId { + return AvailabilityGroupListenerId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + SqlVirtualMachineGroupName: sqlVirtualMachineGroupName, + AvailabilityGroupListenerName: availabilityGroupListenerName, + } +} + +// ParseAvailabilityGroupListenerID parses 'input' into a AvailabilityGroupListenerId +func ParseAvailabilityGroupListenerID(input string) (*AvailabilityGroupListenerId, error) { + parser := resourceids.NewParserFromResourceIdType(AvailabilityGroupListenerId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := AvailabilityGroupListenerId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + if id.AvailabilityGroupListenerName, ok = parsed.Parsed["availabilityGroupListenerName"]; !ok { + return nil, fmt.Errorf("the segment 'availabilityGroupListenerName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseAvailabilityGroupListenerIDInsensitively parses 'input' case-insensitively into a AvailabilityGroupListenerId +// note: this method should only be used for API response data and not user input +func ParseAvailabilityGroupListenerIDInsensitively(input string) (*AvailabilityGroupListenerId, error) { + parser := resourceids.NewParserFromResourceIdType(AvailabilityGroupListenerId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := AvailabilityGroupListenerId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + if id.AvailabilityGroupListenerName, ok = parsed.Parsed["availabilityGroupListenerName"]; !ok { + return nil, fmt.Errorf("the segment 'availabilityGroupListenerName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateAvailabilityGroupListenerID checks that 'input' can be parsed as a Availability Group Listener ID +func ValidateAvailabilityGroupListenerID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseAvailabilityGroupListenerID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Availability Group Listener ID +func (id AvailabilityGroupListenerId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/%s/availabilityGroupListeners/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.SqlVirtualMachineGroupName, id.AvailabilityGroupListenerName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Availability Group Listener ID +func (id AvailabilityGroupListenerId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftSqlVirtualMachine", "Microsoft.SqlVirtualMachine", "Microsoft.SqlVirtualMachine"), + resourceids.StaticSegment("staticSqlVirtualMachineGroups", "sqlVirtualMachineGroups", "sqlVirtualMachineGroups"), + resourceids.UserSpecifiedSegment("sqlVirtualMachineGroupName", "sqlVirtualMachineGroupValue"), + resourceids.StaticSegment("staticAvailabilityGroupListeners", "availabilityGroupListeners", "availabilityGroupListeners"), + resourceids.UserSpecifiedSegment("availabilityGroupListenerName", "availabilityGroupListenerValue"), + } +} + +// String returns a human-readable description of this Availability Group Listener ID +func (id AvailabilityGroupListenerId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Sql Virtual Machine Group Name: %q", id.SqlVirtualMachineGroupName), + fmt.Sprintf("Availability Group Listener Name: %q", id.AvailabilityGroupListenerName), + } + return fmt.Sprintf("Availability Group Listener (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go new file mode 100644 index 000000000000..19b6d09cc574 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go @@ -0,0 +1,127 @@ +package availabilitygrouplisteners + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +var _ resourceids.ResourceId = SqlVirtualMachineGroupId{} + +// SqlVirtualMachineGroupId is a struct representing the Resource ID for a Sql Virtual Machine Group +type SqlVirtualMachineGroupId struct { + SubscriptionId string + ResourceGroupName string + SqlVirtualMachineGroupName string +} + +// NewSqlVirtualMachineGroupID returns a new SqlVirtualMachineGroupId struct +func NewSqlVirtualMachineGroupID(subscriptionId string, resourceGroupName string, sqlVirtualMachineGroupName string) SqlVirtualMachineGroupId { + return SqlVirtualMachineGroupId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + SqlVirtualMachineGroupName: sqlVirtualMachineGroupName, + } +} + +// ParseSqlVirtualMachineGroupID parses 'input' into a SqlVirtualMachineGroupId +func ParseSqlVirtualMachineGroupID(input string) (*SqlVirtualMachineGroupId, error) { + parser := resourceids.NewParserFromResourceIdType(SqlVirtualMachineGroupId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SqlVirtualMachineGroupId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseSqlVirtualMachineGroupIDInsensitively parses 'input' case-insensitively into a SqlVirtualMachineGroupId +// note: this method should only be used for API response data and not user input +func ParseSqlVirtualMachineGroupIDInsensitively(input string) (*SqlVirtualMachineGroupId, error) { + parser := resourceids.NewParserFromResourceIdType(SqlVirtualMachineGroupId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SqlVirtualMachineGroupId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateSqlVirtualMachineGroupID checks that 'input' can be parsed as a Sql Virtual Machine Group ID +func ValidateSqlVirtualMachineGroupID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseSqlVirtualMachineGroupID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.SqlVirtualMachineGroupName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftSqlVirtualMachine", "Microsoft.SqlVirtualMachine", "Microsoft.SqlVirtualMachine"), + resourceids.StaticSegment("staticSqlVirtualMachineGroups", "sqlVirtualMachineGroups", "sqlVirtualMachineGroups"), + resourceids.UserSpecifiedSegment("sqlVirtualMachineGroupName", "sqlVirtualMachineGroupValue"), + } +} + +// String returns a human-readable description of this Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Sql Virtual Machine Group Name: %q", id.SqlVirtualMachineGroupName), + } + return fmt.Sprintf("Sql Virtual Machine Group (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_createorupdate_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_createorupdate_autorest.go new file mode 100644 index 000000000000..d2b982e55204 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_createorupdate_autorest.go @@ -0,0 +1,79 @@ +package availabilitygrouplisteners + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOrUpdateOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// CreateOrUpdate ... +func (c AvailabilityGroupListenersClient) CreateOrUpdate(ctx context.Context, id AvailabilityGroupListenerId, input AvailabilityGroupListener) (result CreateOrUpdateOperationResponse, err error) { + req, err := c.preparerForCreateOrUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "CreateOrUpdate", nil, "Failure preparing request") + return + } + + result, err = c.senderForCreateOrUpdate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "CreateOrUpdate", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// CreateOrUpdateThenPoll performs CreateOrUpdate then polls until it's completed +func (c AvailabilityGroupListenersClient) CreateOrUpdateThenPoll(ctx context.Context, id AvailabilityGroupListenerId, input AvailabilityGroupListener) error { + result, err := c.CreateOrUpdate(ctx, id, input) + if err != nil { + return fmt.Errorf("performing CreateOrUpdate: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after CreateOrUpdate: %+v", err) + } + + return nil +} + +// preparerForCreateOrUpdate prepares the CreateOrUpdate request. +func (c AvailabilityGroupListenersClient) preparerForCreateOrUpdate(ctx context.Context, id AvailabilityGroupListenerId, input AvailabilityGroupListener) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForCreateOrUpdate sends the CreateOrUpdate request. The method will close the +// http.Response Body if it receives an error. +func (c AvailabilityGroupListenersClient) senderForCreateOrUpdate(ctx context.Context, req *http.Request) (future CreateOrUpdateOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + + future.Poller, err = polling.NewPollerFromResponse(ctx, resp, c.Client, req.Method) + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_delete_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_delete_autorest.go new file mode 100644 index 000000000000..2a2ea7120cd2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_delete_autorest.go @@ -0,0 +1,78 @@ +package availabilitygrouplisteners + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Delete ... +func (c AvailabilityGroupListenersClient) Delete(ctx context.Context, id AvailabilityGroupListenerId) (result DeleteOperationResponse, err error) { + req, err := c.preparerForDelete(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "Delete", nil, "Failure preparing request") + return + } + + result, err = c.senderForDelete(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "Delete", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// DeleteThenPoll performs Delete then polls until it's completed +func (c AvailabilityGroupListenersClient) DeleteThenPoll(ctx context.Context, id AvailabilityGroupListenerId) error { + result, err := c.Delete(ctx, id) + if err != nil { + return fmt.Errorf("performing Delete: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Delete: %+v", err) + } + + return nil +} + +// preparerForDelete prepares the Delete request. +func (c AvailabilityGroupListenersClient) preparerForDelete(ctx context.Context, id AvailabilityGroupListenerId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsDelete(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForDelete sends the Delete request. The method will close the +// http.Response Body if it receives an error. +func (c AvailabilityGroupListenersClient) senderForDelete(ctx context.Context, req *http.Request) (future DeleteOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + + future.Poller, err = polling.NewPollerFromResponse(ctx, resp, c.Client, req.Method) + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_get_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_get_autorest.go new file mode 100644 index 000000000000..bbe0b3326d3f --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_get_autorest.go @@ -0,0 +1,97 @@ +package availabilitygrouplisteners + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + Model *AvailabilityGroupListener +} + +type GetOperationOptions struct { + Expand *string +} + +func DefaultGetOperationOptions() GetOperationOptions { + return GetOperationOptions{} +} + +func (o GetOperationOptions) toHeaders() map[string]interface{} { + out := make(map[string]interface{}) + + return out +} + +func (o GetOperationOptions) toQueryString() map[string]interface{} { + out := make(map[string]interface{}) + + if o.Expand != nil { + out["$expand"] = *o.Expand + } + + return out +} + +// Get ... +func (c AvailabilityGroupListenersClient) Get(ctx context.Context, id AvailabilityGroupListenerId, options GetOperationOptions) (result GetOperationResponse, err error) { + req, err := c.preparerForGet(ctx, id, options) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "Get", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "Get", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForGet(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "Get", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForGet prepares the Get request. +func (c AvailabilityGroupListenersClient) preparerForGet(ctx context.Context, id AvailabilityGroupListenerId, options GetOperationOptions) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + for k, v := range options.toQueryString() { + queryParameters[k] = autorest.Encode("query", v) + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithHeaders(options.toHeaders()), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForGet handles the response to the Get request. The method always +// closes the http.Response Body. +func (c AvailabilityGroupListenersClient) responderForGet(resp *http.Response) (result GetOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_listbygroup_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_listbygroup_autorest.go new file mode 100644 index 000000000000..0c0ab85e2f80 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/method_listbygroup_autorest.go @@ -0,0 +1,186 @@ +package availabilitygrouplisteners + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListByGroupOperationResponse struct { + HttpResponse *http.Response + Model *[]AvailabilityGroupListener + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (ListByGroupOperationResponse, error) +} + +type ListByGroupCompleteResult struct { + Items []AvailabilityGroupListener +} + +func (r ListByGroupOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r ListByGroupOperationResponse) LoadMore(ctx context.Context) (resp ListByGroupOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// ListByGroup ... +func (c AvailabilityGroupListenersClient) ListByGroup(ctx context.Context, id SqlVirtualMachineGroupId) (resp ListByGroupOperationResponse, err error) { + req, err := c.preparerForListByGroup(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForListByGroup(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// preparerForListByGroup prepares the ListByGroup request. +func (c AvailabilityGroupListenersClient) preparerForListByGroup(ctx context.Context, id SqlVirtualMachineGroupId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/availabilityGroupListeners", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForListByGroupWithNextLink prepares the ListByGroup request with the given nextLink token. +func (c AvailabilityGroupListenersClient) preparerForListByGroupWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForListByGroup handles the response to the ListByGroup request. The method always +// closes the http.Response Body. +func (c AvailabilityGroupListenersClient) responderForListByGroup(resp *http.Response) (result ListByGroupOperationResponse, err error) { + type page struct { + Values []AvailabilityGroupListener `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result ListByGroupOperationResponse, err error) { + req, err := c.preparerForListByGroupWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForListByGroup(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "availabilitygrouplisteners.AvailabilityGroupListenersClient", "ListByGroup", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} + +// ListByGroupComplete retrieves all of the results into a single object +func (c AvailabilityGroupListenersClient) ListByGroupComplete(ctx context.Context, id SqlVirtualMachineGroupId) (ListByGroupCompleteResult, error) { + return c.ListByGroupCompleteMatchingPredicate(ctx, id, AvailabilityGroupListenerOperationPredicate{}) +} + +// ListByGroupCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c AvailabilityGroupListenersClient) ListByGroupCompleteMatchingPredicate(ctx context.Context, id SqlVirtualMachineGroupId, predicate AvailabilityGroupListenerOperationPredicate) (resp ListByGroupCompleteResult, err error) { + items := make([]AvailabilityGroupListener, 0) + + page, err := c.ListByGroup(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := ListByGroupCompleteResult{ + Items: items, + } + return out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agconfiguration.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agconfiguration.go new file mode 100644 index 000000000000..37fc1b348a7e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agconfiguration.go @@ -0,0 +1,8 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AgConfiguration struct { + Replicas *[]AgReplica `json:"replicas,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agreplica.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agreplica.go new file mode 100644 index 000000000000..87cf65e24bf7 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_agreplica.go @@ -0,0 +1,12 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AgReplica struct { + Commit *Commit `json:"commit,omitempty"` + Failover *Failover `json:"failover,omitempty"` + ReadableSecondary *ReadableSecondary `json:"readableSecondary,omitempty"` + Role *Role `json:"role,omitempty"` + SqlVirtualMachineInstanceId *string `json:"sqlVirtualMachineInstanceId,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistener.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistener.go new file mode 100644 index 000000000000..7ae4bce45830 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistener.go @@ -0,0 +1,16 @@ +package availabilitygrouplisteners + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/systemdata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AvailabilityGroupListener struct { + Id *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Properties *AvailabilityGroupListenerProperties `json:"properties,omitempty"` + SystemData *systemdata.SystemData `json:"systemData,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistenerproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistenerproperties.go new file mode 100644 index 000000000000..47e2e39aeef9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_availabilitygrouplistenerproperties.go @@ -0,0 +1,14 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AvailabilityGroupListenerProperties struct { + AvailabilityGroupConfiguration *AgConfiguration `json:"availabilityGroupConfiguration,omitempty"` + AvailabilityGroupName *string `json:"availabilityGroupName,omitempty"` + CreateDefaultAvailabilityGroupIfNotExist *bool `json:"createDefaultAvailabilityGroupIfNotExist,omitempty"` + LoadBalancerConfigurations *[]LoadBalancerConfiguration `json:"loadBalancerConfigurations,omitempty"` + MultiSubnetIPConfigurations *[]MultiSubnetIPConfiguration `json:"multiSubnetIpConfigurations,omitempty"` + Port *int64 `json:"port,omitempty"` + ProvisioningState *string `json:"provisioningState,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_loadbalancerconfiguration.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_loadbalancerconfiguration.go new file mode 100644 index 000000000000..ec6af3aca89e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_loadbalancerconfiguration.go @@ -0,0 +1,12 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type LoadBalancerConfiguration struct { + LoadBalancerResourceId *string `json:"loadBalancerResourceId,omitempty"` + PrivateIPAddress *PrivateIPAddress `json:"privateIpAddress,omitempty"` + ProbePort *int64 `json:"probePort,omitempty"` + PublicIPAddressResourceId *string `json:"publicIpAddressResourceId,omitempty"` + SqlVirtualMachineInstances *[]string `json:"sqlVirtualMachineInstances,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_multisubnetipconfiguration.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_multisubnetipconfiguration.go new file mode 100644 index 000000000000..357fd454948e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_multisubnetipconfiguration.go @@ -0,0 +1,9 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type MultiSubnetIPConfiguration struct { + PrivateIPAddress PrivateIPAddress `json:"privateIpAddress"` + SqlVirtualMachineInstance string `json:"sqlVirtualMachineInstance"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_privateipaddress.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_privateipaddress.go new file mode 100644 index 000000000000..3fbf130a2213 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/model_privateipaddress.go @@ -0,0 +1,9 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type PrivateIPAddress struct { + IPAddress *string `json:"ipAddress,omitempty"` + SubnetResourceId *string `json:"subnetResourceId,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go new file mode 100644 index 000000000000..60bfffa775ac --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go @@ -0,0 +1,27 @@ +package availabilitygrouplisteners + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type AvailabilityGroupListenerOperationPredicate struct { + Id *string + Name *string + Type *string +} + +func (p AvailabilityGroupListenerOperationPredicate) Matches(input AvailabilityGroupListener) bool { + + if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + return false + } + + if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/version.go new file mode 100644 index 000000000000..8b36ad330a96 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/version.go @@ -0,0 +1,12 @@ +package availabilitygrouplisteners + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2022-02-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/availabilitygrouplisteners/%s", defaultApiVersion) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/README.md b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/README.md new file mode 100644 index 000000000000..1b5c905e2d4c --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/README.md @@ -0,0 +1,116 @@ + +## `github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups` Documentation + +The `sqlvirtualmachinegroups` SDK allows for interaction with the Azure Resource Manager Service `sqlvirtualmachine` (API Version `2022-02-01`). + +This readme covers example usages, but further information on [using this SDK can be found in the project root](https://github.com/hashicorp/go-azure-sdk/tree/main/docs). + +### Import Path + +```go +import "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" +``` + + +### Client Initialization + +```go +client := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupsClientWithBaseURI("https://management.azure.com") +client.Client.Authorizer = authorizer +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.CreateOrUpdate` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue") + +payload := sqlvirtualmachinegroups.SqlVirtualMachineGroup{ + // ... +} + + +if err := client.CreateOrUpdateThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.Delete` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue") + +if err := client.DeleteThenPoll(ctx, id); err != nil { + // handle the error +} +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.Get` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue") + +read, err := client.Get(ctx, id) +if err != nil { + // handle the error +} +if model := read.Model; model != nil { + // do something with the model/response object +} +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.List` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewSubscriptionID("12345678-1234-9876-4563-123456789012") + +// alternatively `client.List(ctx, id)` can be used to do batched pagination +items, err := client.ListComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.ListByResourceGroup` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewResourceGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group") + +// alternatively `client.ListByResourceGroup(ctx, id)` can be used to do batched pagination +items, err := client.ListByResourceGroupComplete(ctx, id) +if err != nil { + // handle the error +} +for _, item := range items { + // do something +} +``` + + +### Example Usage: `SqlVirtualMachineGroupsClient.Update` + +```go +ctx := context.TODO() +id := sqlvirtualmachinegroups.NewSqlVirtualMachineGroupID("12345678-1234-9876-4563-123456789012", "example-resource-group", "sqlVirtualMachineGroupValue") + +payload := sqlvirtualmachinegroups.SqlVirtualMachineGroupUpdate{ + // ... +} + + +if err := client.UpdateThenPoll(ctx, id, payload); err != nil { + // handle the error +} +``` diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/client.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/client.go new file mode 100644 index 000000000000..1ca4860d7327 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/client.go @@ -0,0 +1,18 @@ +package sqlvirtualmachinegroups + +import "github.com/Azure/go-autorest/autorest" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SqlVirtualMachineGroupsClient struct { + Client autorest.Client + baseUri string +} + +func NewSqlVirtualMachineGroupsClientWithBaseURI(endpoint string) SqlVirtualMachineGroupsClient { + return SqlVirtualMachineGroupsClient{ + Client: autorest.NewClientWithUserAgent(userAgent()), + baseUri: endpoint, + } +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/constants.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/constants.go new file mode 100644 index 000000000000..be4233d3cfaa --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/constants.go @@ -0,0 +1,137 @@ +package sqlvirtualmachinegroups + +import "strings" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ClusterConfiguration string + +const ( + ClusterConfigurationDomainful ClusterConfiguration = "Domainful" +) + +func PossibleValuesForClusterConfiguration() []string { + return []string{ + string(ClusterConfigurationDomainful), + } +} + +func parseClusterConfiguration(input string) (*ClusterConfiguration, error) { + vals := map[string]ClusterConfiguration{ + "domainful": ClusterConfigurationDomainful, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ClusterConfiguration(input) + return &out, nil +} + +type ClusterManagerType string + +const ( + ClusterManagerTypeWSFC ClusterManagerType = "WSFC" +) + +func PossibleValuesForClusterManagerType() []string { + return []string{ + string(ClusterManagerTypeWSFC), + } +} + +func parseClusterManagerType(input string) (*ClusterManagerType, error) { + vals := map[string]ClusterManagerType{ + "wsfc": ClusterManagerTypeWSFC, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ClusterManagerType(input) + return &out, nil +} + +type ClusterSubnetType string + +const ( + ClusterSubnetTypeMultiSubnet ClusterSubnetType = "MultiSubnet" + ClusterSubnetTypeSingleSubnet ClusterSubnetType = "SingleSubnet" +) + +func PossibleValuesForClusterSubnetType() []string { + return []string{ + string(ClusterSubnetTypeMultiSubnet), + string(ClusterSubnetTypeSingleSubnet), + } +} + +func parseClusterSubnetType(input string) (*ClusterSubnetType, error) { + vals := map[string]ClusterSubnetType{ + "multisubnet": ClusterSubnetTypeMultiSubnet, + "singlesubnet": ClusterSubnetTypeSingleSubnet, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ClusterSubnetType(input) + return &out, nil +} + +type ScaleType string + +const ( + ScaleTypeHA ScaleType = "HA" +) + +func PossibleValuesForScaleType() []string { + return []string{ + string(ScaleTypeHA), + } +} + +func parseScaleType(input string) (*ScaleType, error) { + vals := map[string]ScaleType{ + "ha": ScaleTypeHA, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := ScaleType(input) + return &out, nil +} + +type SqlVMGroupImageSku string + +const ( + SqlVMGroupImageSkuDeveloper SqlVMGroupImageSku = "Developer" + SqlVMGroupImageSkuEnterprise SqlVMGroupImageSku = "Enterprise" +) + +func PossibleValuesForSqlVMGroupImageSku() []string { + return []string{ + string(SqlVMGroupImageSkuDeveloper), + string(SqlVMGroupImageSkuEnterprise), + } +} + +func parseSqlVMGroupImageSku(input string) (*SqlVMGroupImageSku, error) { + vals := map[string]SqlVMGroupImageSku{ + "developer": SqlVMGroupImageSkuDeveloper, + "enterprise": SqlVMGroupImageSkuEnterprise, + } + if v, ok := vals[strings.ToLower(input)]; ok { + return &v, nil + } + + // otherwise presume it's an undefined value and best-effort it + out := SqlVMGroupImageSku(input) + return &out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go new file mode 100644 index 000000000000..c19b80682862 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go @@ -0,0 +1,127 @@ +package sqlvirtualmachinegroups + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +var _ resourceids.ResourceId = SqlVirtualMachineGroupId{} + +// SqlVirtualMachineGroupId is a struct representing the Resource ID for a Sql Virtual Machine Group +type SqlVirtualMachineGroupId struct { + SubscriptionId string + ResourceGroupName string + SqlVirtualMachineGroupName string +} + +// NewSqlVirtualMachineGroupID returns a new SqlVirtualMachineGroupId struct +func NewSqlVirtualMachineGroupID(subscriptionId string, resourceGroupName string, sqlVirtualMachineGroupName string) SqlVirtualMachineGroupId { + return SqlVirtualMachineGroupId{ + SubscriptionId: subscriptionId, + ResourceGroupName: resourceGroupName, + SqlVirtualMachineGroupName: sqlVirtualMachineGroupName, + } +} + +// ParseSqlVirtualMachineGroupID parses 'input' into a SqlVirtualMachineGroupId +func ParseSqlVirtualMachineGroupID(input string) (*SqlVirtualMachineGroupId, error) { + parser := resourceids.NewParserFromResourceIdType(SqlVirtualMachineGroupId{}) + parsed, err := parser.Parse(input, false) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SqlVirtualMachineGroupId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ParseSqlVirtualMachineGroupIDInsensitively parses 'input' case-insensitively into a SqlVirtualMachineGroupId +// note: this method should only be used for API response data and not user input +func ParseSqlVirtualMachineGroupIDInsensitively(input string) (*SqlVirtualMachineGroupId, error) { + parser := resourceids.NewParserFromResourceIdType(SqlVirtualMachineGroupId{}) + parsed, err := parser.Parse(input, true) + if err != nil { + return nil, fmt.Errorf("parsing %q: %+v", input, err) + } + + var ok bool + id := SqlVirtualMachineGroupId{} + + if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { + return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + } + + if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + } + + if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { + return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + } + + return &id, nil +} + +// ValidateSqlVirtualMachineGroupID checks that 'input' can be parsed as a Sql Virtual Machine Group ID +func ValidateSqlVirtualMachineGroupID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := ParseSqlVirtualMachineGroupID(v); err != nil { + errors = append(errors, err) + } + + return +} + +// ID returns the formatted Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroupName, id.SqlVirtualMachineGroupName) +} + +// Segments returns a slice of Resource ID Segments which comprise this Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) Segments() []resourceids.Segment { + return []resourceids.Segment{ + resourceids.StaticSegment("staticSubscriptions", "subscriptions", "subscriptions"), + resourceids.SubscriptionIdSegment("subscriptionId", "12345678-1234-9876-4563-123456789012"), + resourceids.StaticSegment("staticResourceGroups", "resourceGroups", "resourceGroups"), + resourceids.ResourceGroupSegment("resourceGroupName", "example-resource-group"), + resourceids.StaticSegment("staticProviders", "providers", "providers"), + resourceids.ResourceProviderSegment("staticMicrosoftSqlVirtualMachine", "Microsoft.SqlVirtualMachine", "Microsoft.SqlVirtualMachine"), + resourceids.StaticSegment("staticSqlVirtualMachineGroups", "sqlVirtualMachineGroups", "sqlVirtualMachineGroups"), + resourceids.UserSpecifiedSegment("sqlVirtualMachineGroupName", "sqlVirtualMachineGroupValue"), + } +} + +// String returns a human-readable description of this Sql Virtual Machine Group ID +func (id SqlVirtualMachineGroupId) String() string { + components := []string{ + fmt.Sprintf("Subscription: %q", id.SubscriptionId), + fmt.Sprintf("Resource Group Name: %q", id.ResourceGroupName), + fmt.Sprintf("Sql Virtual Machine Group Name: %q", id.SqlVirtualMachineGroupName), + } + return fmt.Sprintf("Sql Virtual Machine Group (%s)", strings.Join(components, "\n")) +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_createorupdate_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_createorupdate_autorest.go new file mode 100644 index 000000000000..a87be315ed51 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_createorupdate_autorest.go @@ -0,0 +1,79 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type CreateOrUpdateOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// CreateOrUpdate ... +func (c SqlVirtualMachineGroupsClient) CreateOrUpdate(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroup) (result CreateOrUpdateOperationResponse, err error) { + req, err := c.preparerForCreateOrUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "CreateOrUpdate", nil, "Failure preparing request") + return + } + + result, err = c.senderForCreateOrUpdate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "CreateOrUpdate", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// CreateOrUpdateThenPoll performs CreateOrUpdate then polls until it's completed +func (c SqlVirtualMachineGroupsClient) CreateOrUpdateThenPoll(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroup) error { + result, err := c.CreateOrUpdate(ctx, id, input) + if err != nil { + return fmt.Errorf("performing CreateOrUpdate: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after CreateOrUpdate: %+v", err) + } + + return nil +} + +// preparerForCreateOrUpdate prepares the CreateOrUpdate request. +func (c SqlVirtualMachineGroupsClient) preparerForCreateOrUpdate(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroup) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForCreateOrUpdate sends the CreateOrUpdate request. The method will close the +// http.Response Body if it receives an error. +func (c SqlVirtualMachineGroupsClient) senderForCreateOrUpdate(ctx context.Context, req *http.Request) (future CreateOrUpdateOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + + future.Poller, err = polling.NewPollerFromResponse(ctx, resp, c.Client, req.Method) + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_delete_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_delete_autorest.go new file mode 100644 index 000000000000..caefd663e7e4 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_delete_autorest.go @@ -0,0 +1,78 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type DeleteOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Delete ... +func (c SqlVirtualMachineGroupsClient) Delete(ctx context.Context, id SqlVirtualMachineGroupId) (result DeleteOperationResponse, err error) { + req, err := c.preparerForDelete(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Delete", nil, "Failure preparing request") + return + } + + result, err = c.senderForDelete(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Delete", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// DeleteThenPoll performs Delete then polls until it's completed +func (c SqlVirtualMachineGroupsClient) DeleteThenPoll(ctx context.Context, id SqlVirtualMachineGroupId) error { + result, err := c.Delete(ctx, id) + if err != nil { + return fmt.Errorf("performing Delete: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Delete: %+v", err) + } + + return nil +} + +// preparerForDelete prepares the Delete request. +func (c SqlVirtualMachineGroupsClient) preparerForDelete(ctx context.Context, id SqlVirtualMachineGroupId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsDelete(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForDelete sends the Delete request. The method will close the +// http.Response Body if it receives an error. +func (c SqlVirtualMachineGroupsClient) senderForDelete(ctx context.Context, req *http.Request) (future DeleteOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + + future.Poller, err = polling.NewPollerFromResponse(ctx, resp, c.Client, req.Method) + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_get_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_get_autorest.go new file mode 100644 index 000000000000..d707530815b6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_get_autorest.go @@ -0,0 +1,68 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type GetOperationResponse struct { + HttpResponse *http.Response + Model *SqlVirtualMachineGroup +} + +// Get ... +func (c SqlVirtualMachineGroupsClient) Get(ctx context.Context, id SqlVirtualMachineGroupId) (result GetOperationResponse, err error) { + req, err := c.preparerForGet(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Get", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Get", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForGet(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Get", result.HttpResponse, "Failure responding to request") + return + } + + return +} + +// preparerForGet prepares the Get request. +func (c SqlVirtualMachineGroupsClient) preparerForGet(ctx context.Context, id SqlVirtualMachineGroupId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForGet handles the response to the Get request. The method always +// closes the http.Response Body. +func (c SqlVirtualMachineGroupsClient) responderForGet(resp *http.Response) (result GetOperationResponse, err error) { + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result.Model), + autorest.ByClosing()) + result.HttpResponse = resp + + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_list_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_list_autorest.go new file mode 100644 index 000000000000..83352a68ed42 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_list_autorest.go @@ -0,0 +1,187 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListOperationResponse struct { + HttpResponse *http.Response + Model *[]SqlVirtualMachineGroup + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (ListOperationResponse, error) +} + +type ListCompleteResult struct { + Items []SqlVirtualMachineGroup +} + +func (r ListOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r ListOperationResponse) LoadMore(ctx context.Context) (resp ListOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// List ... +func (c SqlVirtualMachineGroupsClient) List(ctx context.Context, id commonids.SubscriptionId) (resp ListOperationResponse, err error) { + req, err := c.preparerForList(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForList(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// preparerForList prepares the List request. +func (c SqlVirtualMachineGroupsClient) preparerForList(ctx context.Context, id commonids.SubscriptionId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForListWithNextLink prepares the List request with the given nextLink token. +func (c SqlVirtualMachineGroupsClient) preparerForListWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForList handles the response to the List request. The method always +// closes the http.Response Body. +func (c SqlVirtualMachineGroupsClient) responderForList(resp *http.Response) (result ListOperationResponse, err error) { + type page struct { + Values []SqlVirtualMachineGroup `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result ListOperationResponse, err error) { + req, err := c.preparerForListWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForList(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "List", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} + +// ListComplete retrieves all of the results into a single object +func (c SqlVirtualMachineGroupsClient) ListComplete(ctx context.Context, id commonids.SubscriptionId) (ListCompleteResult, error) { + return c.ListCompleteMatchingPredicate(ctx, id, SqlVirtualMachineGroupOperationPredicate{}) +} + +// ListCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c SqlVirtualMachineGroupsClient) ListCompleteMatchingPredicate(ctx context.Context, id commonids.SubscriptionId, predicate SqlVirtualMachineGroupOperationPredicate) (resp ListCompleteResult, err error) { + items := make([]SqlVirtualMachineGroup, 0) + + page, err := c.List(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := ListCompleteResult{ + Items: items, + } + return out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_listbyresourcegroup_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_listbyresourcegroup_autorest.go new file mode 100644 index 000000000000..3a062e4084bc --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_listbyresourcegroup_autorest.go @@ -0,0 +1,187 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type ListByResourceGroupOperationResponse struct { + HttpResponse *http.Response + Model *[]SqlVirtualMachineGroup + + nextLink *string + nextPageFunc func(ctx context.Context, nextLink string) (ListByResourceGroupOperationResponse, error) +} + +type ListByResourceGroupCompleteResult struct { + Items []SqlVirtualMachineGroup +} + +func (r ListByResourceGroupOperationResponse) HasMore() bool { + return r.nextLink != nil +} + +func (r ListByResourceGroupOperationResponse) LoadMore(ctx context.Context) (resp ListByResourceGroupOperationResponse, err error) { + if !r.HasMore() { + err = fmt.Errorf("no more pages returned") + return + } + return r.nextPageFunc(ctx, *r.nextLink) +} + +// ListByResourceGroup ... +func (c SqlVirtualMachineGroupsClient) ListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (resp ListByResourceGroupOperationResponse, err error) { + req, err := c.preparerForListByResourceGroup(ctx, id) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", nil, "Failure preparing request") + return + } + + resp.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", resp.HttpResponse, "Failure sending request") + return + } + + resp, err = c.responderForListByResourceGroup(resp.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", resp.HttpResponse, "Failure responding to request") + return + } + return +} + +// preparerForListByResourceGroup prepares the ListByResourceGroup request. +func (c SqlVirtualMachineGroupsClient) preparerForListByResourceGroup(ctx context.Context, id commonids.ResourceGroupId) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(fmt.Sprintf("%s/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups", id.ID())), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// preparerForListByResourceGroupWithNextLink prepares the ListByResourceGroup request with the given nextLink token. +func (c SqlVirtualMachineGroupsClient) preparerForListByResourceGroupWithNextLink(ctx context.Context, nextLink string) (*http.Request, error) { + uri, err := url.Parse(nextLink) + if err != nil { + return nil, fmt.Errorf("parsing nextLink %q: %+v", nextLink, err) + } + queryParameters := map[string]interface{}{} + for k, v := range uri.Query() { + if len(v) == 0 { + continue + } + val := v[0] + val = autorest.Encode("query", val) + queryParameters[k] = val + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsGet(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(uri.Path), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// responderForListByResourceGroup handles the response to the ListByResourceGroup request. The method always +// closes the http.Response Body. +func (c SqlVirtualMachineGroupsClient) responderForListByResourceGroup(resp *http.Response) (result ListByResourceGroupOperationResponse, err error) { + type page struct { + Values []SqlVirtualMachineGroup `json:"value"` + NextLink *string `json:"nextLink"` + } + var respObj page + err = autorest.Respond( + resp, + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&respObj), + autorest.ByClosing()) + result.HttpResponse = resp + result.Model = &respObj.Values + result.nextLink = respObj.NextLink + if respObj.NextLink != nil { + result.nextPageFunc = func(ctx context.Context, nextLink string) (result ListByResourceGroupOperationResponse, err error) { + req, err := c.preparerForListByResourceGroupWithNextLink(ctx, nextLink) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", nil, "Failure preparing request") + return + } + + result.HttpResponse, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", result.HttpResponse, "Failure sending request") + return + } + + result, err = c.responderForListByResourceGroup(result.HttpResponse) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "ListByResourceGroup", result.HttpResponse, "Failure responding to request") + return + } + + return + } + } + return +} + +// ListByResourceGroupComplete retrieves all of the results into a single object +func (c SqlVirtualMachineGroupsClient) ListByResourceGroupComplete(ctx context.Context, id commonids.ResourceGroupId) (ListByResourceGroupCompleteResult, error) { + return c.ListByResourceGroupCompleteMatchingPredicate(ctx, id, SqlVirtualMachineGroupOperationPredicate{}) +} + +// ListByResourceGroupCompleteMatchingPredicate retrieves all of the results and then applied the predicate +func (c SqlVirtualMachineGroupsClient) ListByResourceGroupCompleteMatchingPredicate(ctx context.Context, id commonids.ResourceGroupId, predicate SqlVirtualMachineGroupOperationPredicate) (resp ListByResourceGroupCompleteResult, err error) { + items := make([]SqlVirtualMachineGroup, 0) + + page, err := c.ListByResourceGroup(ctx, id) + if err != nil { + err = fmt.Errorf("loading the initial page: %+v", err) + return + } + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + + for page.HasMore() { + page, err = page.LoadMore(ctx) + if err != nil { + err = fmt.Errorf("loading the next page: %+v", err) + return + } + + if page.Model != nil { + for _, v := range *page.Model { + if predicate.Matches(v) { + items = append(items, v) + } + } + } + } + + out := ListByResourceGroupCompleteResult{ + Items: items, + } + return out, nil +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_update_autorest.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_update_autorest.go new file mode 100644 index 000000000000..9f0084069533 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/method_update_autorest.go @@ -0,0 +1,79 @@ +package sqlvirtualmachinegroups + +import ( + "context" + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/hashicorp/go-azure-helpers/polling" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type UpdateOperationResponse struct { + Poller polling.LongRunningPoller + HttpResponse *http.Response +} + +// Update ... +func (c SqlVirtualMachineGroupsClient) Update(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroupUpdate) (result UpdateOperationResponse, err error) { + req, err := c.preparerForUpdate(ctx, id, input) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Update", nil, "Failure preparing request") + return + } + + result, err = c.senderForUpdate(ctx, req) + if err != nil { + err = autorest.NewErrorWithError(err, "sqlvirtualmachinegroups.SqlVirtualMachineGroupsClient", "Update", result.HttpResponse, "Failure sending request") + return + } + + return +} + +// UpdateThenPoll performs Update then polls until it's completed +func (c SqlVirtualMachineGroupsClient) UpdateThenPoll(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroupUpdate) error { + result, err := c.Update(ctx, id, input) + if err != nil { + return fmt.Errorf("performing Update: %+v", err) + } + + if err := result.Poller.PollUntilDone(); err != nil { + return fmt.Errorf("polling after Update: %+v", err) + } + + return nil +} + +// preparerForUpdate prepares the Update request. +func (c SqlVirtualMachineGroupsClient) preparerForUpdate(ctx context.Context, id SqlVirtualMachineGroupId, input SqlVirtualMachineGroupUpdate) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "api-version": defaultApiVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPatch(), + autorest.WithBaseURL(c.baseUri), + autorest.WithPath(id.ID()), + autorest.WithJSON(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// senderForUpdate sends the Update request. The method will close the +// http.Response Body if it receives an error. +func (c SqlVirtualMachineGroupsClient) senderForUpdate(ctx context.Context, req *http.Request) (future UpdateOperationResponse, err error) { + var resp *http.Response + resp, err = c.Client.Send(req, azure.DoRetryWithRegistration(c.Client)) + if err != nil { + return + } + + future.Poller, err = polling.NewPollerFromResponse(ctx, resp, c.Client, req.Method) + return +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroup.go new file mode 100644 index 000000000000..10657a2ebef1 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroup.go @@ -0,0 +1,18 @@ +package sqlvirtualmachinegroups + +import ( + "github.com/hashicorp/go-azure-helpers/resourcemanager/systemdata" +) + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SqlVirtualMachineGroup struct { + Id *string `json:"id,omitempty"` + Location string `json:"location"` + Name *string `json:"name,omitempty"` + Properties *SqlVirtualMachineGroupProperties `json:"properties,omitempty"` + SystemData *systemdata.SystemData `json:"systemData,omitempty"` + Tags *map[string]string `json:"tags,omitempty"` + Type *string `json:"type,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupproperties.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupproperties.go new file mode 100644 index 000000000000..ad803278894b --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupproperties.go @@ -0,0 +1,14 @@ +package sqlvirtualmachinegroups + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SqlVirtualMachineGroupProperties struct { + ClusterConfiguration *ClusterConfiguration `json:"clusterConfiguration,omitempty"` + ClusterManagerType *ClusterManagerType `json:"clusterManagerType,omitempty"` + ProvisioningState *string `json:"provisioningState,omitempty"` + ScaleType *ScaleType `json:"scaleType,omitempty"` + SqlImageOffer *string `json:"sqlImageOffer,omitempty"` + SqlImageSku *SqlVMGroupImageSku `json:"sqlImageSku,omitempty"` + WsfcDomainProfile *WsfcDomainProfile `json:"wsfcDomainProfile,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupupdate.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupupdate.go new file mode 100644 index 000000000000..25f4e3c5ec7e --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_sqlvirtualmachinegroupupdate.go @@ -0,0 +1,8 @@ +package sqlvirtualmachinegroups + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SqlVirtualMachineGroupUpdate struct { + Tags *map[string]string `json:"tags,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_wsfcdomainprofile.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_wsfcdomainprofile.go new file mode 100644 index 000000000000..73836fd0d549 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/model_wsfcdomainprofile.go @@ -0,0 +1,16 @@ +package sqlvirtualmachinegroups + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type WsfcDomainProfile struct { + ClusterBootstrapAccount *string `json:"clusterBootstrapAccount,omitempty"` + ClusterOperatorAccount *string `json:"clusterOperatorAccount,omitempty"` + ClusterSubnetType *ClusterSubnetType `json:"clusterSubnetType,omitempty"` + DomainFqdn *string `json:"domainFqdn,omitempty"` + FileShareWitnessPath *string `json:"fileShareWitnessPath,omitempty"` + OuPath *string `json:"ouPath,omitempty"` + SqlServiceAccount *string `json:"sqlServiceAccount,omitempty"` + StorageAccountPrimaryKey *string `json:"storageAccountPrimaryKey,omitempty"` + StorageAccountUrl *string `json:"storageAccountUrl,omitempty"` +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go new file mode 100644 index 000000000000..1eac3dc49d0f --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go @@ -0,0 +1,32 @@ +package sqlvirtualmachinegroups + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +type SqlVirtualMachineGroupOperationPredicate struct { + Id *string + Location *string + Name *string + Type *string +} + +func (p SqlVirtualMachineGroupOperationPredicate) Matches(input SqlVirtualMachineGroup) bool { + + if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + return false + } + + if p.Location != nil && *p.Location != input.Location { + return false + } + + if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + return false + } + + if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + return false + } + + return true +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/version.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/version.go new file mode 100644 index 000000000000..65994d7d7331 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/version.go @@ -0,0 +1,12 @@ +package sqlvirtualmachinegroups + +import "fmt" + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See NOTICE.txt in the project root for license information. + +const defaultApiVersion = "2022-02-01" + +func userAgent() string { + return fmt.Sprintf("hashicorp/go-azure-sdk/sqlvirtualmachinegroups/%s", defaultApiVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c5fa5f0240b2..a49444ac24da 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -769,6 +769,8 @@ github.com/hashicorp/go-azure-sdk/resource-manager/servicefabricmanagedcluster/2 github.com/hashicorp/go-azure-sdk/resource-manager/servicelinker/2022-05-01/links github.com/hashicorp/go-azure-sdk/resource-manager/servicelinker/2022-05-01/servicelinker github.com/hashicorp/go-azure-sdk/resource-manager/signalr/2023-02-01/signalr +github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners +github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines github.com/hashicorp/go-azure-sdk/resource-manager/storage/2022-05-01 github.com/hashicorp/go-azure-sdk/resource-manager/storage/2022-05-01/blobcontainers From abbc6924e5d3658c04bf9041bb2b476c45bdc658 Mon Sep 17 00:00:00 2001 From: Yichun Ma Date: Wed, 19 Jul 2023 23:18:25 +0800 Subject: [PATCH 2/5] update --- .github/labeler-issue-triage.yml | 2 +- ...hine_availability_group_listener_schema.go | 120 +++-- .../mssql_virtual_machine_group_schema.go | 27 +- ...ne_availability_group_listener_resource.go | 232 +++++---- ...ailability_group_listener_resource_test.go | 445 +++++++++++++++++- .../mssql_virtual_machine_group_resource.go | 124 ++--- ...sql_virtual_machine_group_resource_test.go | 237 +++++++++- .../mssql/mssql_virtual_machine_resource.go | 48 +- .../mssql/testdata/FirstLogonCommands.xml | 17 + internal/services/mssql/testdata/winrm.ps1 | 18 + .../mssql/validate/sql_image_offer_name.go | 16 + .../validate/sql_image_offer_name_test.go | 55 +++ .../id_availabilitygrouplistener.go | 16 +- .../id_sqlvirtualmachinegroup.go | 12 +- .../availabilitygrouplisteners/predicates.go | 6 +- .../id_sqlvirtualmachinegroup.go | 12 +- .../sqlvirtualmachinegroups/predicates.go | 6 +- ..._availability_group_listener.html.markdown | 187 ++++++++ .../mssql_virtual_machine_group.html.markdown | 98 ++++ 19 files changed, 1327 insertions(+), 351 deletions(-) create mode 100644 internal/services/mssql/testdata/FirstLogonCommands.xml create mode 100644 internal/services/mssql/testdata/winrm.ps1 create mode 100644 internal/services/mssql/validate/sql_image_offer_name.go create mode 100644 internal/services/mssql/validate/sql_image_offer_name_test.go create mode 100644 website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown create mode 100644 website/docs/r/mssql_virtual_machine_group.html.markdown diff --git a/.github/labeler-issue-triage.yml b/.github/labeler-issue-triage.yml index 52ac7464065b..48c1854f7f1d 100644 --- a/.github/labeler-issue-triage.yml +++ b/.github/labeler-issue-triage.yml @@ -229,7 +229,7 @@ service/monitor: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_monitor_((.|\n)*)###' service/mssql: - - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(mssql_database\W+|mssql_database_extended_auditing_policy\W+|mssql_database_vulnerability_assessment_rule_baseline\W+|mssql_elasticpool\W+|mssql_failover_group\W+|mssql_firewall_rule\W+|mssql_job_agent\W+|mssql_job_credential\W+|mssql_outbound_firewall_rule\W+|mssql_server\W+|mssql_server_dns_alias\W+|mssql_server_extended_auditing_policy\W+|mssql_server_microsoft_support_auditing_policy\W+|mssql_server_security_alert_policy\W+|mssql_server_transparent_data_encryption\W+|mssql_server_vulnerability_assessment\W+|mssql_virtual_machine\W+|mssql_virtual_network_rule\W+)((.|\n)*)###' + - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(mssql_database\W+|mssql_database_extended_auditing_policy\W+|mssql_database_vulnerability_assessment_rule_baseline\W+|mssql_elasticpool\W+|mssql_failover_group\W+|mssql_firewall_rule\W+|mssql_job_agent\W+|mssql_job_credential\W+|mssql_outbound_firewall_rule\W+|mssql_server\W+|mssql_server_dns_alias\W+|mssql_server_extended_auditing_policy\W+|mssql_server_microsoft_support_auditing_policy\W+|mssql_server_security_alert_policy\W+|mssql_server_transparent_data_encryption\W+|mssql_server_vulnerability_assessment\W+|mssql_virtual_machine\W+|mssql_virtual_machine_availability_group_listener\W+|mssql_virtual_machine_group\W+|mssql_virtual_network_rule\W+)((.|\n)*)###' service/mssqlmanagedinstance: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_mssql_managed_((.|\n)*)###' diff --git a/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go index b29fb596ebad..f1f0e957bb9e 100644 --- a/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go +++ b/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go @@ -1,6 +1,10 @@ package helper import ( + "bytes" + "fmt" + "strings" + "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" @@ -8,36 +12,27 @@ import ( sqlValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate" networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) type LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { - PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` - PublicIpAddressId string `tfschema:"public_ip_address_id"` - LoadBalancerId string `tfschema:"load_balancer_id"` - ProbePort int `tfschema:"probe_port"` - SqlVirtualMachineInstances []string `tfschema:"sql_virtual_machine_instances"` + PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` + LoadBalancerId string `tfschema:"load_balancer_id"` + ProbePort int `tfschema:"probe_port"` + SqlVirtualMachineIds []string `tfschema:"sql_virtual_machine_ids"` } func LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { return &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, + Type: pluginsdk.TypeList, + Optional: true, + ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, + ForceNew: true, + MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "private_ip_address": PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener(), - "public_ip_address_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ConflictsWith: []string{"load_balancer_configuration.0.private_ip_address"}, - ValidateFunc: networkValidate.PublicIpAddressID, - }, - "load_balancer_id": { Type: pluginsdk.TypeString, Required: true, @@ -47,12 +42,12 @@ func LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener "probe_port": { Type: pluginsdk.TypeInt, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validate.PortNumber, }, - "sql_virtual_machine_instances": { + "sql_virtual_machine_ids": { Type: pluginsdk.TypeSet, Required: true, ForceNew: true, @@ -66,6 +61,32 @@ func LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener } } +type MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { + PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` + SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` +} + +func MultiSubnetIpConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { + return &pluginsdk.Schema{ + Type: pluginsdk.TypeSet, + Optional: true, + ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "private_ip_address": PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + + "sql_virtual_machine_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, + }, + }, + }, + } +} + type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { IpAddress string `tfschema:"ip_address"` SubnetId string `tfschema:"subnet_id"` @@ -73,23 +94,22 @@ type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { func PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { return &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Optional: true, - ForceNew: true, - MinItems: 1, - ConflictsWith: []string{"load_balancer_configuration.0.public_ip_address_id"}, + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "ip_address": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validation.IsIPAddress, }, "subnet_id": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: networkValidate.SubnetID, }, @@ -99,56 +119,70 @@ func PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener() *plugi } type ReplicaMsSqlVirtualMachineAvailabilityGroupListener struct { - SqlVirtualMachineInstanceId string `tfschema:"sql_virtual_machine_instance_id"` - Role string `tfschema:"role"` - Commit string `tfschema:"commit"` - Failover string `tfschema:"failover"` - ReadableSecondary string `tfschema:"readable_secondary"` + SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` + Role string `tfschema:"role"` + Commit string `tfschema:"commit"` + Failover string `tfschema:"failover"` + ReadableSecondary string `tfschema:"readable_secondary"` } func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { return &pluginsdk.Schema{ Type: pluginsdk.TypeSet, - Optional: true, + Required: true, ForceNew: true, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "sql_virtual_machine_instance_id": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: sqlValidate.SqlVirtualMachineID, - DiffSuppressFunc: suppress.CaseDifference, + "sql_virtual_machine_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: sqlValidate.SqlVirtualMachineID, }, "role": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.RolePrimary), string(availabilitygrouplisteners.RoleSecondary)}, false), }, "commit": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.CommitSynchronousCommit), string(availabilitygrouplisteners.CommitAsynchronousCommit)}, false), }, "failover": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.FailoverManual), string(availabilitygrouplisteners.FailoverAutomatic)}, false), }, "readable_secondary": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.ReadableSecondaryNo), string(availabilitygrouplisteners.ReadableSecondaryReadOnly), string(availabilitygrouplisteners.ReadableSecondaryAll)}, false), }, }, }, + Set: ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash, } } + +func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash(v interface{}) int { + var buf bytes.Buffer + + if m, ok := v.(map[string]interface{}); ok { + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["sql_virtual_machine_id"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", m["role"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["commit"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["failover"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["readable_secondary"].(string))) + } + + return pluginsdk.HashString(buf.String()) +} diff --git a/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go index d60c54efe676..7f5ca3176458 100644 --- a/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go +++ b/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go @@ -12,7 +12,6 @@ type WsfcDomainProfile struct { ClusterBootstrapAccountName string `tfschema:"cluster_bootstrap_account_name"` ClusterOperatorAccountName string `tfschema:"cluster_operator_account_name"` SqlServiceAccountName string `tfschema:"sql_service_account_name"` - FileShareWitnessPath string `tfschema:"file_share_witness_path"` StorageAccountUrl string `tfschema:"storage_account_url"` StorageAccountPrimaryKey string `tfschema:"storage_account_primary_key"` ClusterSubnetType string `tfschema:"cluster_subnet_type"` @@ -25,6 +24,16 @@ func WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup() *pluginsdk.Sc MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ + "cluster_subnet_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sqlvirtualmachinegroups.ClusterSubnetTypeMultiSubnet), + string(sqlvirtualmachinegroups.ClusterSubnetTypeSingleSubnet), + }, false), + }, + "fqdn": { Type: pluginsdk.TypeString, Required: true, @@ -60,13 +69,6 @@ func WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup() *pluginsdk.Sc ValidateFunc: validation.StringIsNotEmpty, }, - "file_share_witness_path": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "storage_account_url": { Type: pluginsdk.TypeString, Optional: true, @@ -80,15 +82,6 @@ func WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup() *pluginsdk.Sc Sensitive: true, ValidateFunc: validation.StringIsNotEmpty, }, - - "cluster_subnet_type": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(sqlvirtualmachinegroups.ClusterSubnetTypeMultiSubnet), - string(sqlvirtualmachinegroups.ClusterSubnetTypeSingleSubnet), - }, false), - }, }, }, } diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go index 9b08be63f498..5779d68bf727 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go @@ -5,8 +5,8 @@ import ( "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/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -24,15 +24,14 @@ import ( type MsSqlVirtualMachineAvailabilityGroupListenerResource struct{} type MsSqlVirtualMachineAvailabilityGroupListenerModel struct { - Name string `tfschema:"name"` - ResourceGroup string `tfschema:"resource_group_name"` - SqlVirtualMachineGroupName string `tfschema:"sql_virtual_machine_group_name"` - AvailabilityGroupName string `tfschema:"availability_group_name"` - - CreateDefaultAvailabilityGroup bool `tfschema:"create_default_availability_group"` - Port int `tfschema:"port"` - LoadBalancerConfiguration []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"load_balancer_configuration"` - Replica []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"replica"` + Name string `tfschema:"name"` + SqlVirtualMachineGroupId string `tfschema:"sql_virtual_machine_group_id"` + AvailabilityGroupName string `tfschema:"availability_group_name"` + + Port int `tfschema:"port"` + LoadBalancerConfiguration []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"load_balancer_configuration"` + MultiSubnetIpConfiguration []helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"multi_subnet_ip_configuration"` + Replica []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"replica"` } var _ sdk.Resource = MsSqlVirtualMachineAvailabilityGroupListenerResource{} @@ -55,16 +54,14 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, + ValidateFunc: validation.StringLenBetween(1, 15), }, - "resource_group_name": commonschema.ResourceGroupName(), - - "sql_virtual_machine_group_name": { + "sql_virtual_machine_group_id": { Type: pluginsdk.TypeString, - Optional: true, + Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 15), + ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineGroupID, }, "availability_group_name": { @@ -73,13 +70,6 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st ForceNew: true, }, - "create_default_availability_group": { - Type: pluginsdk.TypeBool, - Optional: true, - Default: true, - ForceNew: true, - }, - "port": { Type: pluginsdk.TypeInt, Optional: true, @@ -89,6 +79,8 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st "load_balancer_configuration": helper.LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + "multi_subnet_ip_configuration": helper.MultiSubnetIpConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + "replica": helper.ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener(), } } @@ -109,9 +101,14 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Create() sdk.Resou client := metadata.Client.MSSQL.VirtualMachinesAvailabilityGroupListenersClient subscriptionId := metadata.Client.Account.SubscriptionId - id := availabilitygrouplisteners.NewAvailabilityGroupListenerID(subscriptionId, model.ResourceGroup, model.SqlVirtualMachineGroupName, model.Name) + sqlVirtualMachineGroupId, err := availabilitygrouplisteners.ParseSqlVirtualMachineGroupID(model.SqlVirtualMachineGroupId) + if err != nil { + return err + } - existing, err := client.Get(ctx, id, availabilitygrouplisteners.GetOperationOptions{Expand: utils.String("AvailabilityGroupConfiguration")}) + id := availabilitygrouplisteners.NewAvailabilityGroupListenerID(subscriptionId, sqlVirtualMachineGroupId.ResourceGroupName, sqlVirtualMachineGroupId.SqlVirtualMachineGroupName, model.Name) + + existing, err := client.Get(ctx, id, availabilitygrouplisteners.GetOperationOptions{Expand: pointer.To("AvailabilityGroupConfiguration")}) if err != nil { if !response.WasNotFound(existing.HttpResponse) { return fmt.Errorf("checking for presence of existing %s: %+v", id, err) @@ -121,11 +118,6 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Create() sdk.Resou return metadata.ResourceRequiresImport(r.ResourceType(), id) } - lbConfigs, err := expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(model.LoadBalancerConfiguration) - if err != nil { - return err - } - replicas, err := expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(model.Replica) if err != nil { return err @@ -133,16 +125,31 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Create() sdk.Resou parameters := availabilitygrouplisteners.AvailabilityGroupListener{ Properties: &availabilitygrouplisteners.AvailabilityGroupListenerProperties{ - AvailabilityGroupName: utils.String(model.AvailabilityGroupName), - LoadBalancerConfigurations: lbConfigs, - CreateDefaultAvailabilityGroupIfNotExist: utils.Bool(model.CreateDefaultAvailabilityGroup), - Port: utils.Int64(int64(model.Port)), + AvailabilityGroupName: pointer.To(model.AvailabilityGroupName), + CreateDefaultAvailabilityGroupIfNotExist: pointer.To(true), + Port: pointer.To(int64(model.Port)), AvailabilityGroupConfiguration: &availabilitygrouplisteners.AgConfiguration{ Replicas: replicas, }, }, } + if model.LoadBalancerConfiguration != nil && len(model.LoadBalancerConfiguration) != 0 { + lbConfigs, err := expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(model.LoadBalancerConfiguration) + if err != nil { + return err + } + parameters.Properties.LoadBalancerConfigurations = lbConfigs + } + + if model.MultiSubnetIpConfiguration != nil && len(model.MultiSubnetIpConfiguration) != 0 { + multiSubnetIpConfiguration, err := expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(model.MultiSubnetIpConfiguration) + if err != nil { + return err + } + parameters.Properties.MultiSubnetIPConfigurations = multiSubnetIpConfiguration + } + if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } @@ -165,7 +172,7 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Read() sdk.Resourc return err } - resp, err := client.Get(ctx, *id, availabilitygrouplisteners.GetOperationOptions{Expand: utils.String("AvailabilityGroupConfiguration")}) + resp, err := client.Get(ctx, *id, availabilitygrouplisteners.GetOperationOptions{Expand: pointer.To("AvailabilityGroupConfiguration")}) if err != nil { if response.WasNotFound(resp.HttpResponse) { return metadata.MarkAsGone(id) @@ -174,31 +181,15 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Read() sdk.Resourc } state := MsSqlVirtualMachineAvailabilityGroupListenerModel{ - Name: id.AvailabilityGroupListenerName, - ResourceGroup: id.ResourceGroupName, - SqlVirtualMachineGroupName: id.SqlVirtualMachineGroupName, + Name: id.AvailabilityGroupListenerName, + SqlVirtualMachineGroupId: availabilitygrouplisteners.NewSqlVirtualMachineGroupID(id.SubscriptionId, id.ResourceGroupName, id.SqlVirtualMachineGroupName).ID(), } if model := resp.Model; model != nil { if props := model.Properties; props != nil { - avGroupName := "" - if props.AvailabilityGroupName != nil { - avGroupName = *props.AvailabilityGroupName - } - state.AvailabilityGroupName = avGroupName - - createDefaultAvailabilityGroup := true - if props.CreateDefaultAvailabilityGroupIfNotExist != nil { - createDefaultAvailabilityGroup = *props.CreateDefaultAvailabilityGroupIfNotExist - } - state.CreateDefaultAvailabilityGroup = createDefaultAvailabilityGroup - - var port int64 - if props.Port != nil { - port = *props.Port - } - state.Port = int(port) + state.AvailabilityGroupName = pointer.From(props.AvailabilityGroupName) + state.Port = int(pointer.From(props.Port)) avGroupListenerLbConfigs, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(props.LoadBalancerConfigurations, id.SubscriptionId) if err != nil { @@ -206,10 +197,16 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Read() sdk.Resourc } state.LoadBalancerConfiguration = avGroupListenerLbConfigs + multiSubnetIpConfiguration, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(props.MultiSubnetIPConfigurations, id.SubscriptionId) + if err != nil { + return fmt.Errorf("setting `multi_subnet_ip_configuration`: %+v", err) + } + state.MultiSubnetIpConfiguration = multiSubnetIpConfiguration + if props.AvailabilityGroupConfiguration != nil { if props.AvailabilityGroupConfiguration.Replicas != nil { - replicas, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(props.AvailabilityGroupConfiguration.Replicas) + replicas, err := flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(props.AvailabilityGroupConfiguration.Replicas, id.SubscriptionId) if err != nil { return fmt.Errorf("setting `replica`: %+v", err) } @@ -249,7 +246,7 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration for _, lb := range lbConfigs { lbConfig := availabilitygrouplisteners.LoadBalancerConfiguration{ - ProbePort: utils.Int64(int64(lb.ProbePort)), + ProbePort: pointer.To(int64(lb.ProbePort)), } parsedLbId := "" @@ -260,10 +257,10 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration } parsedLbId = id.ID() } - lbConfig.LoadBalancerResourceId = utils.String(parsedLbId) + lbConfig.LoadBalancerResourceId = pointer.To(parsedLbId) var parsedIds []interface{} - for _, sqlVmId := range lb.SqlVirtualMachineInstances { + for _, sqlVmId := range lb.SqlVirtualMachineIds { parsedId, err := parse.SqlVirtualMachineID(sqlVmId) if err != nil { return nil, err @@ -279,15 +276,28 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration } lbConfig.PrivateIPAddress = privateIpAddress } + results = append(results, lbConfig) + } + return &results, nil +} + +func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(multiSubnetIpConfiguration []helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.MultiSubnetIPConfiguration, error) { + results := make([]availabilitygrouplisteners.MultiSubnetIPConfiguration, 0) + + for _, item := range multiSubnetIpConfiguration { + + config := availabilitygrouplisteners.MultiSubnetIPConfiguration{ + SqlVirtualMachineInstance: item.SqlVirtualMachineId, + } - if publicIp := lb.PublicIpAddressId; publicIp != "" { - id, err := networkParse.PublicIpAddressID(publicIp) + if item.PrivateIpAddress != nil { + privateIpAddress, err := expandMsSqlVirtualMachinePrivateIpAddress(item.PrivateIpAddress) if err != nil { return nil, err } - lbConfig.PublicIPAddressResourceId = utils.String(id.ID()) + config.PrivateIPAddress = *privateIpAddress } - results = append(results, lbConfig) + results = append(results, config) } return &results, nil } @@ -311,9 +321,9 @@ func expandMsSqlVirtualMachinePrivateIpAddress(input []helper.PrivateIpAddressMs } return &availabilitygrouplisteners.PrivateIPAddress{ - IPAddress: utils.String(ipAddress), + IPAddress: pointer.To(ipAddress), - SubnetResourceId: utils.String(subnetId), + SubnetResourceId: pointer.To(subnetId), }, nil } @@ -334,31 +344,21 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio privateIpAddress = flattenedPrivateIp } - publicIpAddressId := "" - if lbConfig.PublicIPAddressResourceId != nil { - publicIpAddressId = *lbConfig.PublicIPAddressResourceId - } - loadBalancerId := "" if lbConfig.LoadBalancerResourceId != nil { - id, err := lbParse.LoadBalancerID(*lbConfig.LoadBalancerResourceId) + id, err := lbParse.LoadBalancerID(pointer.From(lbConfig.LoadBalancerResourceId)) if err != nil { return nil, err } loadBalancerId = id.ID() } - var probePort int64 - if lbConfig.ProbePort != nil { - probePort = *lbConfig.ProbePort - } - var sqlVirtualMachineIds []string if lbConfig.SqlVirtualMachineInstances != nil { sqlVirtualMachineIds = *lbConfig.SqlVirtualMachineInstances var parsedIds []string for _, sqlVmId := range sqlVirtualMachineIds { - parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineID(sqlVmId) + parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(sqlVmId) // get correct casing for subscription in id newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { @@ -370,11 +370,40 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio } v := helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ - PrivateIpAddress: privateIpAddress, - PublicIpAddressId: publicIpAddressId, - LoadBalancerId: loadBalancerId, - ProbePort: int(probePort), - SqlVirtualMachineInstances: sqlVirtualMachineIds, + PrivateIpAddress: privateIpAddress, + LoadBalancerId: loadBalancerId, + ProbePort: int(pointer.From(lbConfig.ProbePort)), + SqlVirtualMachineIds: sqlVirtualMachineIds, + } + + results = append(results, v) + } + return results, nil +} + +func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(input *[]availabilitygrouplisteners.MultiSubnetIPConfiguration, subscriptionId string) ([]helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) + if input == nil || len(*input) == 0 { + return results, nil + } + + for _, config := range *input { + var privateIpAddress []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener + flattenedPrivateIp, err := flattenPrivateIpAddress(config.PrivateIPAddress) + if err != nil { + return nil, err + } + privateIpAddress = flattenedPrivateIp + + parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(config.SqlVirtualMachineInstance) + newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) + if err != nil { + return nil, err + } + + v := helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ + PrivateIpAddress: privateIpAddress, + SqlVirtualMachineId: newId.ID(), } results = append(results, v) @@ -410,20 +439,14 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []helpe results := make([]availabilitygrouplisteners.AgReplica, 0) for _, rep := range replicas { - - role := availabilitygrouplisteners.Role(rep.Role) - commit := availabilitygrouplisteners.Commit(rep.Commit) - failover := availabilitygrouplisteners.Failover(rep.Failover) - readableSecondary := availabilitygrouplisteners.ReadableSecondary(rep.ReadableSecondary) - replica := availabilitygrouplisteners.AgReplica{ - Role: &role, - Commit: &commit, - Failover: &failover, - ReadableSecondary: &readableSecondary, + Role: pointer.To(availabilitygrouplisteners.Role(rep.Role)), + Commit: pointer.To(availabilitygrouplisteners.Commit(rep.Commit)), + Failover: pointer.To(availabilitygrouplisteners.Failover(rep.Failover)), + ReadableSecondary: pointer.To(availabilitygrouplisteners.ReadableSecondary(rep.ReadableSecondary)), } - sqlVirtualMachineId := rep.SqlVirtualMachineInstanceId + sqlVirtualMachineId := rep.SqlVirtualMachineId if sqlVirtualMachineId != "" { id, err := sqlvirtualmachines.ParseSqlVirtualMachineID(sqlVirtualMachineId) if err != nil { @@ -431,14 +454,14 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []helpe } sqlVirtualMachineId = id.ID() } - replica.SqlVirtualMachineInstanceId = utils.String(sqlVirtualMachineId) + replica.SqlVirtualMachineInstanceId = pointer.To(sqlVirtualMachineId) results = append(results, replica) } return &results, nil } -func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availabilitygrouplisteners.AgReplica) ([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, error) { +func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availabilitygrouplisteners.AgReplica, subscriptionId string) ([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, error) { results := make([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, 0) if input == nil || len(*input) == 0 { return results, nil @@ -448,32 +471,37 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availa sqlVirtualMachineInstanceId := "" if replica.SqlVirtualMachineInstanceId != nil { - parsedSqlVmId, err := sqlvirtualmachines.ParseSqlVirtualMachineID(*replica.SqlVirtualMachineInstanceId) + parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(*replica.SqlVirtualMachineInstanceId) + if err != nil { + return nil, err + } + + newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { return nil, err } - sqlVirtualMachineInstanceId = parsedSqlVmId.ID() + sqlVirtualMachineInstanceId = newId.ID() } v := helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener{ - SqlVirtualMachineInstanceId: sqlVirtualMachineInstanceId, + SqlVirtualMachineId: sqlVirtualMachineInstanceId, } if replica.Role != nil { - v.Role = string(*replica.Role) + v.Role = string(pointer.From(replica.Role)) } if replica.Commit != nil { - v.Commit = string(*replica.Commit) + v.Commit = string(pointer.From(replica.Commit)) } if replica.Failover != nil { - v.Failover = string(*replica.Failover) + v.Failover = string(pointer.From(replica.Failover)) } if replica.ReadableSecondary != nil { - v.ReadableSecondary = string(*replica.ReadableSecondary) + v.ReadableSecondary = string(pointer.From(replica.ReadableSecondary)) } results = append(results, v) diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go index 5050edde914d..90825c457d23 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" @@ -16,17 +17,47 @@ import ( type MsSqlVirtualMachineAvailabilityGroupListenerResource struct{} -func TestAccMsSqlVirtualMachineAvailabilityGroupListenerResource_basic(t *testing.T) { +func TestAccMsSqlVirtualMachineAvailabilityGroupListener_loadBalancerConfiguration(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_availability_group_listener", "test") r := MsSqlVirtualMachineAvailabilityGroupListenerResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.basic(), + Config: r.configureDomain(data), + }, + { + PreConfig: func() { time.Sleep(12 * time.Minute) }, + Config: r.setDomainUser(data), + }, + { + Config: r.loadBalancerConfiguration(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccMsSqlVirtualMachineAvailabilityGroupListener_multiSubnetIpConfiguration(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine_availability_group_listener", "test") + r := MsSqlVirtualMachineAvailabilityGroupListenerResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.configureDomain(data), + }, + { + PreConfig: func() { time.Sleep(12 * time.Minute) }, + Config: r.setDomainUser(data), + }, + { + Config: r.multiSubnetIpConfiguration(data), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), }, + data.ImportStep(), }) } @@ -47,36 +78,406 @@ func (MsSqlVirtualMachineAvailabilityGroupListenerResource) Exists(ctx context.C return utils.Bool(resp.Model != nil), nil } -// TODO add proper test -func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) basic() string { +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) loadBalancerConfiguration(data acceptance.TestData) string { return fmt.Sprintf(` -resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { - name = "MyListener" - resource_group_name = // *** resource_group_name - availability_group_name = "default2" - port = 1432 - create_default_availability_group = true - sql_virtual_machine_group_name = // *** sql_virtual_machine_group_name +%[1]s + +resource "azurerm_lb" "test" { + name = "acctestlb-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + sku = "Standard" + + frontend_ip_configuration { + name = "Internal" + private_ip_address_allocation = "Static" + private_ip_address_version = "IPv4" + private_ip_address = "10.0.2.10" + subnet_id = azurerm_subnet.domain_clients[0].id + } + + lifecycle { + ignore_changes = [ + frontend_ip_configuration + ] + } +} +resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { + name = "acctestli-%[3]s" + availability_group_name = "availabilitygroup1" + port = 1433 + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id load_balancer_configuration { + load_balancer_id = azurerm_lb.test.id + probe_port = 51572 + private_ip_address { - ip_address = "10.0.2.8" - subnet_id = + ip_address = "10.0.2.11" + subnet_id = azurerm_subnet.domain_clients[0].id } - load_balancer_id = // *** load_balancer_id - probe_port = 51572 - sql_virtual_machine_instances = [ // *** sql_virtual_machine_instances ] + sql_virtual_machine_ids = [ + azurerm_mssql_virtual_machine.test[0].id, + azurerm_mssql_virtual_machine.test[1].id + ] } replica { - sql_virtual_machine_instance_id = // *** sql_virtual_machine_instance_id - role = "PRIMARY" - commit = "SYNCHRONOUS_COMMIT" - failover = "AUTOMATIC" - readable_secondary = "ALL" + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id + role = "Secondary" + commit = "Asynchronous_Commit" + failover = "Manual" + readable_secondary = "No" + } + + replica { + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id + role = "Primary" + commit = "Synchronous_Commit" + failover = "Automatic" + readable_secondary = "All" + } +} +`, r.template(data, true), data.RandomInteger, data.RandomString) +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) multiSubnetIpConfiguration(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { + name = "acctestli-%[2]s" + availability_group_name = "default" + port = 1433 + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id + + multi_subnet_ip_configuration { + private_ip_address { + ip_address = "10.0.2.11" + subnet_id = azurerm_subnet.domain_clients[0].id + } + + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id + } + + multi_subnet_ip_configuration { + private_ip_address { + ip_address = "10.0.3.11" + subnet_id = azurerm_subnet.domain_clients[1].id + } + + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id + } + + replica { + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id + role = "Primary" + commit = "Synchronous_Commit" + failover = "Automatic" + readable_secondary = "All" + } + + replica { + sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id + role = "Secondary" + commit = "Asynchronous_Commit" + failover = "Manual" + readable_secondary = "Read_Only" + } +} +`, r.template(data, false), data.RandomString) +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) template(data acceptance.TestData, isSingleSubnet bool) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_subnet" "domain_clients" { + count = %[5]t ? 1 : 2 + + name = "domain-clients-${count.index}" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.${count.index + 2}.0/24"] +} + +resource "azurerm_network_interface" "client_single_subnet" { + count = %[5]t ? 2 : 0 + + name = "acctestnic-client-${count.index}-%[3]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "primary" + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.domain_clients[0].id + } +} + +resource "azurerm_network_interface" "client_multi_subnet" { + count = %[5]t ? 0 : 2 + + name = "acctestnic-client-${count.index}-%[3]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "primary" + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.domain_clients[count.index].id + } + + lifecycle { + ignore_changes = [ + ip_configuration + ] + } +} + +resource "azurerm_availability_set" "test" { + name = "acctestavset-%[3]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_windows_virtual_machine" "client" { + count = 2 + + name = "acctest-${count.index}-%[4]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + size = "Standard_F2" + admin_username = local.admin_username + admin_password = local.admin_password + custom_data = local.custom_data + availability_set_id = azurerm_availability_set.test.id + + network_interface_ids = [ + %[5]t ? azurerm_network_interface.client_single_subnet[count.index].id : azurerm_network_interface.client_multi_subnet[count.index].id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftSQLServer" + offer = "SQL2019-WS2019" + sku = "SQLDEV" + version = "latest" + } + +} + +resource "azurerm_virtual_machine_extension" "join_domain" { + count = 2 + + name = "join-domain-${count.index}" + virtual_machine_id = azurerm_windows_virtual_machine.client[count.index].id + publisher = "Microsoft.Compute" + type = "JsonADDomainExtension" + type_handler_version = "1.3" + + settings = jsonencode({ + Name = local.active_directory_domain_name, + OUPath = "", + User = "${local.active_directory_domain_name}\\${local.admin_username}", + Restart = "true", + Options = "3" + }) + + protected_settings = jsonencode({ + Password = local.admin_password + }) +} + +resource "azurerm_mssql_virtual_machine" "test" { + count = 2 + + virtual_machine_id = azurerm_windows_virtual_machine.client[count.index].id + sql_license_type = "PAYG" + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id + + wsfc_domain_credentials { + cluster_bootstrap_account_password = local.admin_password + cluster_operator_account_password = local.admin_password + sql_service_account_password = local.admin_password + } + + depends_on = [ + azurerm_virtual_machine_extension.join_domain + ] +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%[4]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_mssql_virtual_machine_group" "test" { + name = "acctestgr-%[4]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sql_image_offer = "SQL2019-WS2019" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = local.active_directory_domain_name + + cluster_bootstrap_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + cluster_operator_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + sql_service_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + storage_account_url = azurerm_storage_account.test.primary_blob_endpoint + storage_account_primary_key = azurerm_storage_account.test.primary_access_key + cluster_subnet_type = %[5]t ? "SingleSubnet" : "MultiSubnet" + } +} +`, r.setDomainUser(data), data.Locations.Primary, data.RandomInteger, data.RandomString, isSingleSubnet) +} + +func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) configureDomain(data acceptance.TestData) string { + return fmt.Sprintf( + ` +%[1]s + +resource "azurerm_virtual_machine_extension" "custom_script" { + name = "create-active-directory-forest" + virtual_machine_id = azurerm_windows_virtual_machine.domain_controller.id + publisher = "Microsoft.Compute" + type = "CustomScriptExtension" + type_handler_version = "1.9" + settings = < + + cmd /c "mkdir C:\terraform" + Create the Terraform working directory + 11 + + + cmd /c "copy C:\AzureData\CustomData.bin C:\terraform\winrm.ps1" + Move the CustomData file to the working directory + 12 + + + powershell.exe -sta -ExecutionPolicy Unrestricted -file C:\terraform\winrm.ps1 + Execute the WinRM enabling script + 13 + + diff --git a/internal/services/mssql/testdata/winrm.ps1 b/internal/services/mssql/testdata/winrm.ps1 new file mode 100644 index 000000000000..6c40c1229627 --- /dev/null +++ b/internal/services/mssql/testdata/winrm.ps1 @@ -0,0 +1,18 @@ +$Cert = New-SelfSignedCertificate -DnsName $RemoteHostName, $ComputerName ` + -CertStoreLocation "cert:\LocalMachine\My" ` + -FriendlyName "Test WinRM Cert" + +$Cert | Out-String + +$Thumbprint = $Cert.Thumbprint + +Write-Host "Enable HTTPS in WinRM" +$WinRmHttps = "@{Hostname=`"$RemoteHostName`"; CertificateThumbprint=`"$Thumbprint`"}" +winrm create winrm/config/Listener?Address=*+Transport=HTTPS $WinRmHttps + +Write-Host "Set Basic Auth in WinRM" +$WinRmBasic = "@{Basic=`"true`"}" +winrm set winrm/config/service/Auth $WinRmBasic + +Write-Host "Open Firewall Port" +netsh advfirewall firewall add rule name="Windows Remote Management (HTTPS-In)" dir=in action=allow protocol=TCP localport=5985 diff --git a/internal/services/mssql/validate/sql_image_offer_name.go b/internal/services/mssql/validate/sql_image_offer_name.go new file mode 100644 index 000000000000..96be78dc555f --- /dev/null +++ b/internal/services/mssql/validate/sql_image_offer_name.go @@ -0,0 +1,16 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func SqlImageOfferName(v interface{}, k string) (warnings []string, errors []error) { + value := v.(string) + + if !regexp.MustCompile(`^SQL[A-Za-z0-9]*-WS[A-Za-z0-9]*$`).MatchString(value) { + errors = append(errors, fmt.Errorf("%q should be in the form SQL-WS, for example SQL2019-WS2019: %q", k, value)) + } + + return warnings, errors +} diff --git a/internal/services/mssql/validate/sql_image_offer_name_test.go b/internal/services/mssql/validate/sql_image_offer_name_test.go new file mode 100644 index 000000000000..5201ab5432e5 --- /dev/null +++ b/internal/services/mssql/validate/sql_image_offer_name_test.go @@ -0,0 +1,55 @@ +package validate + +import ( + "testing" +) + +func TestSqlImageOfferName(t *testing.T) { + cases := []struct { + Value string + ErrCount int + }{ + // Valid cases + { + Value: "SQL2019-WS2019", + ErrCount: 0, + }, + { + Value: "SQL2022-WS2012R2", + ErrCount: 0, + }, + // Invalid Cases + { + Value: "", + ErrCount: 1, + }, + { + Value: "2019-WS2019", + ErrCount: 1, + }, + { + Value: "SQL2019-2019", + ErrCount: 1, + }, + { + Value: "SQL2019-WS20.19", + ErrCount: 1, + }, + { + Value: "SQL20.19-WS2019", + ErrCount: 1, + }, + { + Value: "SQL2019.WS2019", + ErrCount: 1, + }, + } + + for i, tc := range cases { + _, errors := SqlImageOfferName(tc.Value, "sql_image_offer") + + if len(errors) != tc.ErrCount { + t.Fatalf("Case %d: Encountered %d error(s), expected %d", i, len(errors), tc.ErrCount) + } + } +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go index 8f483e83d298..4836dca5df5b 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_availabilitygrouplistener.go @@ -42,19 +42,19 @@ func ParseAvailabilityGroupListenerID(input string) (*AvailabilityGroupListenerI id := AvailabilityGroupListenerId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } if id.AvailabilityGroupListenerName, ok = parsed.Parsed["availabilityGroupListenerName"]; !ok { - return nil, fmt.Errorf("the segment 'availabilityGroupListenerName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "availabilityGroupListenerName", *parsed) } return &id, nil @@ -73,19 +73,19 @@ func ParseAvailabilityGroupListenerIDInsensitively(input string) (*AvailabilityG id := AvailabilityGroupListenerId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } if id.AvailabilityGroupListenerName, ok = parsed.Parsed["availabilityGroupListenerName"]; !ok { - return nil, fmt.Errorf("the segment 'availabilityGroupListenerName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "availabilityGroupListenerName", *parsed) } return &id, nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go index 19b6d09cc574..b2f7143c89fa 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/id_sqlvirtualmachinegroup.go @@ -40,15 +40,15 @@ func ParseSqlVirtualMachineGroupID(input string) (*SqlVirtualMachineGroupId, err id := SqlVirtualMachineGroupId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } return &id, nil @@ -67,15 +67,15 @@ func ParseSqlVirtualMachineGroupIDInsensitively(input string) (*SqlVirtualMachin id := SqlVirtualMachineGroupId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } return &id, nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go index 60bfffa775ac..fff382e98c77 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners/predicates.go @@ -11,15 +11,15 @@ type AvailabilityGroupListenerOperationPredicate struct { func (p AvailabilityGroupListenerOperationPredicate) Matches(input AvailabilityGroupListener) bool { - if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { return false } - if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { return false } - if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { return false } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go index c19b80682862..9893b19ac616 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/id_sqlvirtualmachinegroup.go @@ -40,15 +40,15 @@ func ParseSqlVirtualMachineGroupID(input string) (*SqlVirtualMachineGroupId, err id := SqlVirtualMachineGroupId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } return &id, nil @@ -67,15 +67,15 @@ func ParseSqlVirtualMachineGroupIDInsensitively(input string) (*SqlVirtualMachin id := SqlVirtualMachineGroupId{} if id.SubscriptionId, ok = parsed.Parsed["subscriptionId"]; !ok { - return nil, fmt.Errorf("the segment 'subscriptionId' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "subscriptionId", *parsed) } if id.ResourceGroupName, ok = parsed.Parsed["resourceGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'resourceGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "resourceGroupName", *parsed) } if id.SqlVirtualMachineGroupName, ok = parsed.Parsed["sqlVirtualMachineGroupName"]; !ok { - return nil, fmt.Errorf("the segment 'sqlVirtualMachineGroupName' was not found in the resource id %q", input) + return nil, resourceids.NewSegmentNotSpecifiedError(id, "sqlVirtualMachineGroupName", *parsed) } return &id, nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go index 1eac3dc49d0f..d3878f312b54 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups/predicates.go @@ -12,7 +12,7 @@ type SqlVirtualMachineGroupOperationPredicate struct { func (p SqlVirtualMachineGroupOperationPredicate) Matches(input SqlVirtualMachineGroup) bool { - if p.Id != nil && (input.Id == nil && *p.Id != *input.Id) { + if p.Id != nil && (input.Id == nil || *p.Id != *input.Id) { return false } @@ -20,11 +20,11 @@ func (p SqlVirtualMachineGroupOperationPredicate) Matches(input SqlVirtualMachin return false } - if p.Name != nil && (input.Name == nil && *p.Name != *input.Name) { + if p.Name != nil && (input.Name == nil || *p.Name != *input.Name) { return false } - if p.Type != nil && (input.Type == nil && *p.Type != *input.Type) { + if p.Type != nil && (input.Type == nil || *p.Type != *input.Type) { return false } diff --git a/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown new file mode 100644 index 000000000000..c806b2d61b7f --- /dev/null +++ b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown @@ -0,0 +1,187 @@ +--- +subcategory: "Database" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_mssql_virtual_machine_availability_group_listener" +description: |- + Manages a Microsoft SQL Virtual Machine Availability Group Listener. +--- + +# azurerm_mssql_virtual_machine_availability_group_listener + +Manages a Microsoft SQL Virtual Machine Availability Group Listener. + +## Example Usage + +```hcl +data "azurerm_subnet" "example" { + name = "examplesubnet" + virtual_network_name = "examplevnet" + resource_group_name = "example-resources" +} + +data "azurerm_lb" "example" { + name = "example-lb" + resource_group_name = "example-resources" +} + +data "azurerm_virtual_machine" "example" { + count = 2 + + name = "example-vm" + resource_group_name = "example-resources" +} + +resource "azurerm_mssql_virtual_machine_group" "example" { + name = "examplegroup" + resource_group_name = "example-resources" + location = "West Europe" + + sql_image_offer = "SQL2017-WS2016" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = "testdomain.com" + cluster_subnet_type = "SingleSubnet" + } +} + +resource "azurerm_mssql_virtual_machine" "example" { + count = 2 + + virtual_machine_id = data.azurerm_virtual_machine.example[count.index].id + sql_license_type = "PAYG" + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.example.id + + wsfc_domain_credentials { + cluster_bootstrap_account_password = "P@ssw0rd1234!" + cluster_operator_account_password = "P@ssw0rd1234!" + sql_service_account_password = "P@ssw0rd1234!" + } +} + +resource "azurerm_mssql_virtual_machine_availability_group_listener" "example" { + name = "listener1" + availability_group_name = "availabilitygroup1" + port = 1433 + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.example.id + + load_balancer_configuration { + load_balancer_id = data.azurerm_lb.example.id + probe_port = 51572 + + private_ip_address { + ip_address = "10.0.2.11" + subnet_id = data.azurerm_subnet.example.id + } + + sql_virtual_machine_ids = [ + azurerm_mssql_virtual_machine.example[0].id, + azurerm_mssql_virtual_machine.example[1].id + ] + } + + replica { + sql_virtual_machine_id = azurerm_mssql_virtual_machine.example[0].id + role = "Primary" + commit = "Synchronous_Commit" + failover = "Automatic" + readable_secondary = "All" + } + + replica { + sql_virtual_machine_id = azurerm_mssql_virtual_machine.example[1].id + role = "Secondary" + commit = "Asynchronous_Commit" + failover = "Manual" + readable_secondary = "No" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for the Microsoft SQL Virtual Machine Availability Group Listener. Changing this forces a new resource to be created. + +* `sql_virtual_machine_group_id` - (Required) ID of the SQL Virtual Machine Group to create the listener. Changing this forces a new resource to be created. + +* `availability_group_name` - (Optional) Name of the Availability Group. Changing this forces a new resource to be created. + +* `load_balancer_configuration` - (Optional) A `load_balancer_configuration` block as defined below. Changing this forces a new resource to be created. + +~> **NOTE:** Either one of `load_balancer_configuration` or `multi_subnet_ip_configuration` must be specified. + +* `multi_subnet_ip_configuration` - (Optional) One or more `multi_subnet_ip_configuration` blocks as defined below. Changing this forces a new resource to be created. + +* `port` - (Optional) Port of the listener. Changing this forces a new resource to be created. + +* `replica` - (Optional) One or more `replica` blocks as defined below. Changing this forces a new resource to be created. + +--- + +A `load_balancer_configuration` block supports the following: + +* `load_balancer_id` - (Required) The ID of the Load Balancer. Changing this forces a new resource to be created. + +* `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. + +* `probe_port` - (Required) Probe port of the listener. Changing this forces a new resource to be created. + +* `sql_virtual_machine_ids` - (Required) Specifies a list of IDs of the SQL Virtual Machine. Changing this forces a new resource to be created. + +~> **NOTE:** `sql_virtual_machine_ids` should match with the SQL Virtual Machines specified in `replica`. + +--- + +A `multi_subnet_ip_configuration` block supports the following: + +* `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. + +* `sql_virtual_machine_id` - (Required) ID of the Sql Virtual Machine. Changing this forces a new resource to be created. + +~> **NOTE:** `sql_virtual_machine_id` should match with the SQL Virtual Machines specified in `replica`. + +--- + +A `private_ip_address` block supports the following: + +* `ip_address` - (Required) IP Address. Changing this forces a new resource to be created. + +* `subnet_id` - (Required) The ID of the Subnet. Changing this forces a new resource to be created. + +--- + +A `replica` block supports the following: + +* `commit` - (Required) Replica commit mode in availability group. Possible values are `Synchronous_Commit` and `Asynchronous_Commit`. Changing this forces a new resource to be created. + +* `failover` - (Required) Replica failover mode in availability group. Possible values are `Manual` and `Automatic`. Changing this forces a new resource to be created. + +* `readable_secondary` - (Required) Replica readable secondary mode in availability group. Possible values are `No`, `Read_Only` and `All`. Changing this forces a new resource to be created. + +* `role` - (Required) Replica Role in availability group. Possible values are `Primary` and `Secondary`. Changing this forces a new resource to be created. + +* `sql_virtual_machine_id` - (Required) The ID of the SQL Virtual Machine. Changing this forces a new resource to be created. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Microsoft SQL Virtual Machine Availability Group Listener. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Microsoft SQL Virtual Machine Availability Group Listener. +* `read` - (Defaults to 5 minutes) Used when retrieving the Microsoft SQL Virtual Machine Availability Group Listener. +* `delete` - (Defaults to 30 minutes) Used when deleting the Microsoft SQL Virtual Machine Availability Group Listener. + +## Import + +Microsoft SQL Virtual Machine Availability Group Listeners can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_mssql_virtual_machine_availability_group_listener.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/vmgroup1/availabilityGroupListeners/listener1 +``` diff --git a/website/docs/r/mssql_virtual_machine_group.html.markdown b/website/docs/r/mssql_virtual_machine_group.html.markdown new file mode 100644 index 000000000000..04998db69102 --- /dev/null +++ b/website/docs/r/mssql_virtual_machine_group.html.markdown @@ -0,0 +1,98 @@ +--- +subcategory: "Database" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_mssql_virtual_machine_group" +description: |- + Manages a Microsoft SQL Virtual Machine Group. +--- + +# azurerm_mssql_virtual_machine_group + +Manages a Microsoft SQL Virtual Machine Group. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_mssql_virtual_machine_group" "example" { + name = "examplegroup" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + + sql_image_offer = "SQL2017-WS2016" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = "testdomain.com" + cluster_subnet_type = "SingleSubnet" + } +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for the Microsoft SQL Virtual Machine Group. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the Resource Group where the Microsoft SQL Virtual Machine Group should exist. Changing this forces a new resource to be created. + +* `location` - (Required) The Azure Region where the Microsoft SQL Virtual Machine Group should exist. Changing this forces a new resource to be created. + +* `sql_image_offer` - (Required) The offer type of the marketplace image cluster to be used by the SQL Virtual Machine Group. Changing this forces a new resource to be created. + +* `sql_image_sku` - (Required) The sku type of the marketplace image cluster to be used by the SQL Virtual Machine Group. Possible values are `Developer` and `Enterprise`. + +* `wsfc_domain_profile` - (Required) A `wsfc_domain_profile` block as defined below. + +* `tags` - (Optional) A mapping of tags which should be assigned to the Microsoft SQL Virtual Machine Group. + +--- + +A `wsfc_domain_profile` block supports the following: + +* `cluster_subnet_type` - (Required) Subnet type of the SQL Virtual Machine cluster. Possible values are `MultiSubnet` and `SingleSubnet`. Changing this forces a new resource to be created. + +* `fqdn` - (Required) Fully qualified name of the domain. Changing this forces a new resource to be created. + +* `cluster_bootstrap_account_name` - (Optional) Account name used for creating cluster. Changing this forces a new resource to be created. + +* `cluster_operator_account_name` - (Optional) Account name used for operating cluster. Changing this forces a new resource to be created. + +* `ou_path` - (Optional) Organizational Unit path in which the nodes and cluster will be present. Changing this forces a new resource to be created. + +* `sql_service_account_name` - (Optional) Account name under which SQL service will run on all participating SQL virtual machines in the cluster. Changing this forces a new resource to be created. + +* `storage_account_primary_key` - (Optional) Primary key of the Storage Account. + +* `storage_account_url` - (Optional) The SAS URL to the Storage Container of the witness storage account. Changing this forces a new resource to be created. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Microsoft SQL Virtual Machine Group. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Microsoft SQL Virtual Machine Group. +* `read` - (Defaults to 5 minutes) Used when retrieving the Microsoft SQL Virtual Machine Group. +* `update` - (Defaults to 30 minutes) Used when updating the Microsoft SQL Virtual Machine Group. +* `delete` - (Defaults to 30 minutes) Used when deleting the Microsoft SQL Virtual Machine Group. + +## Import + +Microsoft SQL Virtual Machine Groups can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_mssql_virtual_machine_group.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.SqlVirtualMachine/sqlVirtualMachineGroups/vmgroup1 +``` + + + From 91c8a075ca89a2ca59faeef068c69ee278da420e Mon Sep 17 00:00:00 2001 From: Yichun Ma Date: Tue, 8 Aug 2023 13:41:08 +0800 Subject: [PATCH 3/5] resolve comments --- ...hine_availability_group_listener_schema.go | 188 ------------ .../mssql_virtual_machine_group_schema.go | 88 ------ ...ne_availability_group_listener_resource.go | 270 ++++++++++++++---- ...ailability_group_listener_resource_test.go | 35 ++- .../mssql_virtual_machine_group_resource.go | 132 ++++++--- ...sql_virtual_machine_group_resource_test.go | 2 +- .../mssql/mssql_virtual_machine_resource.go | 21 +- .../mssql_virtual_machine_resource_test.go | 167 +++++++++++ .../r/mssql_virtual_machine.html.markdown | 14 + ..._availability_group_listener.html.markdown | 22 +- .../mssql_virtual_machine_group.html.markdown | 14 +- 11 files changed, 547 insertions(+), 406 deletions(-) delete mode 100644 internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go delete mode 100644 internal/services/mssql/helper/mssql_virtual_machine_group_schema.go diff --git a/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go deleted file mode 100644 index f1f0e957bb9e..000000000000 --- a/internal/services/mssql/helper/mssql_virtual_machine_availability_group_listener_schema.go +++ /dev/null @@ -1,188 +0,0 @@ -package helper - -import ( - "bytes" - "fmt" - "strings" - - "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" - "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" - "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" - lbValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" - sqlValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate" - networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" -) - -type LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { - PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` - LoadBalancerId string `tfschema:"load_balancer_id"` - ProbePort int `tfschema:"probe_port"` - SqlVirtualMachineIds []string `tfschema:"sql_virtual_machine_ids"` -} - -func LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Optional: true, - ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "private_ip_address": PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener(), - - "load_balancer_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: lbValidate.LoadBalancerID, - }, - - "probe_port": { - Type: pluginsdk.TypeInt, - Required: true, - ForceNew: true, - ValidateFunc: validate.PortNumber, - }, - - "sql_virtual_machine_ids": { - Type: pluginsdk.TypeSet, - Required: true, - ForceNew: true, - Elem: &pluginsdk.Schema{ - Type: pluginsdk.TypeString, - ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, - }, - }, - }, - }, - } -} - -type MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { - PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` - SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` -} - -func MultiSubnetIpConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeSet, - Optional: true, - ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "private_ip_address": PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener(), - - "sql_virtual_machine_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, - }, - }, - }, - } -} - -type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { - IpAddress string `tfschema:"ip_address"` - SubnetId string `tfschema:"subnet_id"` -} - -func PrivateIpAddressSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "ip_address": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.IsIPAddress, - }, - - "subnet_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: networkValidate.SubnetID, - }, - }, - }, - } -} - -type ReplicaMsSqlVirtualMachineAvailabilityGroupListener struct { - SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` - Role string `tfschema:"role"` - Commit string `tfschema:"commit"` - Failover string `tfschema:"failover"` - ReadableSecondary string `tfschema:"readable_secondary"` -} - -func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeSet, - Required: true, - ForceNew: true, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "sql_virtual_machine_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: sqlValidate.SqlVirtualMachineID, - }, - - "role": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.RolePrimary), string(availabilitygrouplisteners.RoleSecondary)}, false), - }, - - "commit": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.CommitSynchronousCommit), string(availabilitygrouplisteners.CommitAsynchronousCommit)}, false), - }, - - "failover": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.FailoverManual), string(availabilitygrouplisteners.FailoverAutomatic)}, false), - }, - - "readable_secondary": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.ReadableSecondaryNo), string(availabilitygrouplisteners.ReadableSecondaryReadOnly), string(availabilitygrouplisteners.ReadableSecondaryAll)}, false), - }, - }, - }, - Set: ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash, - } -} - -func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash(v interface{}) int { - var buf bytes.Buffer - - if m, ok := v.(map[string]interface{}); ok { - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["sql_virtual_machine_id"].(string)))) - buf.WriteString(fmt.Sprintf("%s-", m["role"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["commit"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["failover"].(string))) - buf.WriteString(fmt.Sprintf("%s-", m["readable_secondary"].(string))) - } - - return pluginsdk.HashString(buf.String()) -} diff --git a/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go b/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go deleted file mode 100644 index 7f5ca3176458..000000000000 --- a/internal/services/mssql/helper/mssql_virtual_machine_group_schema.go +++ /dev/null @@ -1,88 +0,0 @@ -package helper - -import ( - "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" -) - -type WsfcDomainProfile struct { - Fqdn string `tfschema:"fqdn"` - OuPath string `tfschema:"ou_path"` - ClusterBootstrapAccountName string `tfschema:"cluster_bootstrap_account_name"` - ClusterOperatorAccountName string `tfschema:"cluster_operator_account_name"` - SqlServiceAccountName string `tfschema:"sql_service_account_name"` - StorageAccountUrl string `tfschema:"storage_account_url"` - StorageAccountPrimaryKey string `tfschema:"storage_account_primary_key"` - ClusterSubnetType string `tfschema:"cluster_subnet_type"` -} - -func WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup() *pluginsdk.Schema { - return &pluginsdk.Schema{ - Type: pluginsdk.TypeList, - Required: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "cluster_subnet_type": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(sqlvirtualmachinegroups.ClusterSubnetTypeMultiSubnet), - string(sqlvirtualmachinegroups.ClusterSubnetTypeSingleSubnet), - }, false), - }, - - "fqdn": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "ou_path": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "cluster_bootstrap_account_name": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "cluster_operator_account_name": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "sql_service_account_name": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "storage_account_url": { - Type: pluginsdk.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - - "storage_account_primary_key": { - Type: pluginsdk.TypeString, - Optional: true, - Sensitive: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - }, - }, - } -} diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go index 5779d68bf727..ec3da23da21e 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go @@ -1,8 +1,10 @@ package mssql import ( + "bytes" "context" "fmt" + "strings" "time" "github.com/hashicorp/go-azure-helpers/lang/pointer" @@ -13,9 +15,11 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" lbParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/helper" + lbValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/parse" + sqlValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate" networkParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" + networkValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/utils" @@ -28,10 +32,35 @@ type MsSqlVirtualMachineAvailabilityGroupListenerModel struct { SqlVirtualMachineGroupId string `tfschema:"sql_virtual_machine_group_id"` AvailabilityGroupName string `tfschema:"availability_group_name"` - Port int `tfschema:"port"` - LoadBalancerConfiguration []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"load_balancer_configuration"` - MultiSubnetIpConfiguration []helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"multi_subnet_ip_configuration"` - Replica []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"replica"` + Port int `tfschema:"port"` + LoadBalancerConfiguration []LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"load_balancer_configuration"` + MultiSubnetIpConfiguration []MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"multi_subnet_ip_configuration"` + Replica []ReplicaMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"replica"` +} + +type LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { + PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` + LoadBalancerId string `tfschema:"load_balancer_id"` + ProbePort int `tfschema:"probe_port"` + SqlVirtualMachineIds []string `tfschema:"sql_virtual_machine_ids"` +} + +type MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { + PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` + SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` +} + +type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { + IpAddress string `tfschema:"ip_address"` + SubnetId string `tfschema:"subnet_id"` +} + +type ReplicaMsSqlVirtualMachineAvailabilityGroupListener struct { + SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` + Role string `tfschema:"role"` + Commit string `tfschema:"commit"` + FailoverMode string `tfschema:"failover_mode"` + ReadableSecondary string `tfschema:"readable_secondary"` } var _ sdk.Resource = MsSqlVirtualMachineAvailabilityGroupListenerResource{} @@ -77,11 +106,150 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st ValidateFunc: validate.PortNumber, }, - "load_balancer_configuration": helper.LoadBalancerConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + "load_balancer_configuration": { + Type: pluginsdk.TypeList, + Optional: true, + ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "private_ip_address": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ip_address": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.IsIPAddress, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, + }, + }, + }, + + "load_balancer_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: lbValidate.LoadBalancerID, + }, + + "probe_port": { + Type: pluginsdk.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validate.PortNumber, + }, + + "sql_virtual_machine_ids": { + Type: pluginsdk.TypeSet, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, + }, + }, + }, + }, + }, + + "multi_subnet_ip_configuration": { + Type: pluginsdk.TypeSet, + Optional: true, + ExactlyOneOf: []string{"load_balancer_configuration", "multi_subnet_ip_configuration"}, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "private_ip_address": { + Type: pluginsdk.TypeList, + Required: true, + ForceNew: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ip_address": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.IsIPAddress, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, + }, + }, + }, + + "sql_virtual_machine_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, + }, + }, + }, + }, + + "replica": { + Type: pluginsdk.TypeSet, + Required: true, + ForceNew: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "sql_virtual_machine_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: sqlValidate.SqlVirtualMachineID, + }, + + "role": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.RolePrimary), string(availabilitygrouplisteners.RoleSecondary)}, false), + }, + + "commit": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.CommitSynchronousCommit), string(availabilitygrouplisteners.CommitAsynchronousCommit)}, false), + }, - "multi_subnet_ip_configuration": helper.MultiSubnetIpConfigurationSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + "failover_mode": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.FailoverManual), string(availabilitygrouplisteners.FailoverAutomatic)}, false), + }, - "replica": helper.ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListener(), + "readable_secondary": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{string(availabilitygrouplisteners.ReadableSecondaryNo), string(availabilitygrouplisteners.ReadableSecondaryReadOnly), string(availabilitygrouplisteners.ReadableSecondaryAll)}, false), + }, + }, + }, + Set: ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash, + }, } } @@ -240,7 +408,7 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Delete() sdk.Resou } } -func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(lbConfigs []helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.LoadBalancerConfiguration, error) { +func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(lbConfigs []LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.LoadBalancerConfiguration, error) { results := make([]availabilitygrouplisteners.LoadBalancerConfiguration, 0) for _, lb := range lbConfigs { @@ -281,7 +449,7 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration return &results, nil } -func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(multiSubnetIpConfiguration []helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.MultiSubnetIPConfiguration, error) { +func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(multiSubnetIpConfiguration []MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.MultiSubnetIPConfiguration, error) { results := make([]availabilitygrouplisteners.MultiSubnetIPConfiguration, 0) for _, item := range multiSubnetIpConfiguration { @@ -302,7 +470,7 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguratio return &results, nil } -func expandMsSqlVirtualMachinePrivateIpAddress(input []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener) (*availabilitygrouplisteners.PrivateIPAddress, error) { +func expandMsSqlVirtualMachinePrivateIpAddress(input []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener) (*availabilitygrouplisteners.PrivateIPAddress, error) { if len(input) == 0 { return nil, nil } @@ -327,15 +495,15 @@ func expandMsSqlVirtualMachinePrivateIpAddress(input []helper.PrivateIpAddressMs }, nil } -func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(input *[]availabilitygrouplisteners.LoadBalancerConfiguration, subscriptionId string) ([]helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { - results := make([]helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) +func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(input *[]availabilitygrouplisteners.LoadBalancerConfiguration, subscriptionId string) ([]LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) if input == nil || len(*input) == 0 { return results, nil } for _, lbConfig := range *input { - var privateIpAddress []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener + var privateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener if lbConfig.PrivateIPAddress != nil { flattenedPrivateIp, err := flattenPrivateIpAddress(*lbConfig.PrivateIPAddress) if err != nil { @@ -359,7 +527,8 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio var parsedIds []string for _, sqlVmId := range sqlVirtualMachineIds { parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(sqlVmId) - // get correct casing for subscription in id + + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { return nil, err @@ -369,7 +538,7 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio sqlVirtualMachineIds = parsedIds } - v := helper.LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ + v := LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ PrivateIpAddress: privateIpAddress, LoadBalancerId: loadBalancerId, ProbePort: int(pointer.From(lbConfig.ProbePort)), @@ -381,14 +550,14 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio return results, nil } -func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(input *[]availabilitygrouplisteners.MultiSubnetIPConfiguration, subscriptionId string) ([]helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { - results := make([]helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) +func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(input *[]availabilitygrouplisteners.MultiSubnetIPConfiguration, subscriptionId string) ([]MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) if input == nil || len(*input) == 0 { return results, nil } for _, config := range *input { - var privateIpAddress []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener + var privateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener flattenedPrivateIp, err := flattenPrivateIpAddress(config.PrivateIPAddress) if err != nil { return nil, err @@ -396,12 +565,14 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfigurati privateIpAddress = flattenedPrivateIp parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(config.SqlVirtualMachineInstance) + + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { return nil, err } - v := helper.MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ + v := MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ PrivateIpAddress: privateIpAddress, SqlVirtualMachineId: newId.ID(), } @@ -411,19 +582,15 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfigurati return results, nil } -func flattenPrivateIpAddress(input availabilitygrouplisteners.PrivateIPAddress) ([]helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener, error) { - - privateIpAddress := helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{} +func flattenPrivateIpAddress(input availabilitygrouplisteners.PrivateIPAddress) ([]PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener, error) { - ipAddress := "" - if input.IPAddress != nil { - ipAddress = *input.IPAddress + privateIpAddress := PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{ + IpAddress: pointer.From(input.IPAddress), } - privateIpAddress.IpAddress = ipAddress subnetId := "" if input.SubnetResourceId != nil { - id, err := networkParse.SubnetID(*input.SubnetResourceId) + id, err := networkParse.SubnetIDInsensitively(*input.SubnetResourceId) if err != nil { return nil, err } @@ -432,17 +599,17 @@ func flattenPrivateIpAddress(input availabilitygrouplisteners.PrivateIPAddress) privateIpAddress.SubnetId = subnetId - return []helper.PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{privateIpAddress}, nil + return []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{privateIpAddress}, nil } -func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.AgReplica, error) { +func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []ReplicaMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.AgReplica, error) { results := make([]availabilitygrouplisteners.AgReplica, 0) for _, rep := range replicas { replica := availabilitygrouplisteners.AgReplica{ Role: pointer.To(availabilitygrouplisteners.Role(rep.Role)), Commit: pointer.To(availabilitygrouplisteners.Commit(rep.Commit)), - Failover: pointer.To(availabilitygrouplisteners.Failover(rep.Failover)), + Failover: pointer.To(availabilitygrouplisteners.Failover(rep.FailoverMode)), ReadableSecondary: pointer.To(availabilitygrouplisteners.ReadableSecondary(rep.ReadableSecondary)), } @@ -461,8 +628,8 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []helpe return &results, nil } -func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availabilitygrouplisteners.AgReplica, subscriptionId string) ([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, error) { - results := make([]helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener, 0) +func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availabilitygrouplisteners.AgReplica, subscriptionId string) ([]ReplicaMsSqlVirtualMachineAvailabilityGroupListener, error) { + results := make([]ReplicaMsSqlVirtualMachineAvailabilityGroupListener, 0) if input == nil || len(*input) == 0 { return results, nil } @@ -476,6 +643,7 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availa return nil, err } + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { return nil, err @@ -484,27 +652,29 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availa sqlVirtualMachineInstanceId = newId.ID() } - v := helper.ReplicaMsSqlVirtualMachineAvailabilityGroupListener{ + v := ReplicaMsSqlVirtualMachineAvailabilityGroupListener{ SqlVirtualMachineId: sqlVirtualMachineInstanceId, - } - - if replica.Role != nil { - v.Role = string(pointer.From(replica.Role)) - } - - if replica.Commit != nil { - v.Commit = string(pointer.From(replica.Commit)) - } - - if replica.Failover != nil { - v.Failover = string(pointer.From(replica.Failover)) - } - - if replica.ReadableSecondary != nil { - v.ReadableSecondary = string(pointer.From(replica.ReadableSecondary)) + Role: string(pointer.From(replica.Role)), + Commit: string(pointer.From(replica.Commit)), + FailoverMode: string(pointer.From(replica.Failover)), + ReadableSecondary: string(pointer.From(replica.ReadableSecondary)), } results = append(results, v) } return results, nil } + +func ReplicaSchemaMsSqlVirtualMachineAvailabilityGroupListenerHash(v interface{}) int { + var buf bytes.Buffer + + if m, ok := v.(map[string]interface{}); ok { + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["sql_virtual_machine_id"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", m["role"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["commit"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["failover_mode"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["readable_secondary"].(string))) + } + + return pluginsdk.HashString(buf.String()) +} diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go index 90825c457d23..2f95b227f57e 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go @@ -129,7 +129,7 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id role = "Secondary" commit = "Asynchronous_Commit" - failover = "Manual" + failover_mode = "Manual" readable_secondary = "No" } @@ -137,7 +137,7 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id role = "Primary" commit = "Synchronous_Commit" - failover = "Automatic" + failover_mode = "Automatic" readable_secondary = "All" } } @@ -176,7 +176,7 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id role = "Primary" commit = "Synchronous_Commit" - failover = "Automatic" + failover_mode = "Automatic" readable_secondary = "All" } @@ -184,7 +184,7 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id role = "Secondary" commit = "Asynchronous_Commit" - failover = "Manual" + failover_mode = "Manual" readable_secondary = "Read_Only" } } @@ -196,7 +196,7 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) template(data acce %[1]s resource "azurerm_subnet" "domain_clients" { - count = %[5]t ? 1 : 2 + count = %[4]t ? 1 : 2 name = "domain-clients-${count.index}" resource_group_name = azurerm_resource_group.test.name @@ -205,9 +205,9 @@ resource "azurerm_subnet" "domain_clients" { } resource "azurerm_network_interface" "client_single_subnet" { - count = %[5]t ? 2 : 0 + count = %[4]t ? 2 : 0 - name = "acctestnic-client-${count.index}-%[3]d" + name = "acctestnic-client-${count.index}-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -219,9 +219,9 @@ resource "azurerm_network_interface" "client_single_subnet" { } resource "azurerm_network_interface" "client_multi_subnet" { - count = %[5]t ? 0 : 2 + count = %[4]t ? 0 : 2 - name = "acctestnic-client-${count.index}-%[3]d" + name = "acctestnic-client-${count.index}-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name @@ -239,7 +239,7 @@ resource "azurerm_network_interface" "client_multi_subnet" { } resource "azurerm_availability_set" "test" { - name = "acctestavset-%[3]d" + name = "acctestavset-%[2]d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name } @@ -247,7 +247,7 @@ resource "azurerm_availability_set" "test" { resource "azurerm_windows_virtual_machine" "client" { count = 2 - name = "acctest-${count.index}-%[4]s" + name = "acctest-${count.index}-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name size = "Standard_F2" @@ -257,7 +257,7 @@ resource "azurerm_windows_virtual_machine" "client" { availability_set_id = azurerm_availability_set.test.id network_interface_ids = [ - %[5]t ? azurerm_network_interface.client_single_subnet[count.index].id : azurerm_network_interface.client_multi_subnet[count.index].id, + %[4]t ? azurerm_network_interface.client_single_subnet[count.index].id : azurerm_network_interface.client_multi_subnet[count.index].id, ] os_disk { @@ -271,7 +271,6 @@ resource "azurerm_windows_virtual_machine" "client" { sku = "SQLDEV" version = "latest" } - } resource "azurerm_virtual_machine_extension" "join_domain" { @@ -303,7 +302,7 @@ resource "azurerm_mssql_virtual_machine" "test" { sql_license_type = "PAYG" sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id - wsfc_domain_credentials { + wsfc_domain_credential { cluster_bootstrap_account_password = local.admin_password cluster_operator_account_password = local.admin_password sql_service_account_password = local.admin_password @@ -315,7 +314,7 @@ resource "azurerm_mssql_virtual_machine" "test" { } resource "azurerm_storage_account" "test" { - name = "acctestsa%[4]s" + name = "acctestsa%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name account_tier = "Standard" @@ -323,7 +322,7 @@ resource "azurerm_storage_account" "test" { } resource "azurerm_mssql_virtual_machine_group" "test" { - name = "acctestgr-%[4]s" + name = "acctestgr-%[3]s" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name sql_image_offer = "SQL2019-WS2019" @@ -337,10 +336,10 @@ resource "azurerm_mssql_virtual_machine_group" "test" { sql_service_account_name = "${local.admin_username}@${local.active_directory_domain_name}" storage_account_url = azurerm_storage_account.test.primary_blob_endpoint storage_account_primary_key = azurerm_storage_account.test.primary_access_key - cluster_subnet_type = %[5]t ? "SingleSubnet" : "MultiSubnet" + cluster_subnet_type = %[4]t ? "SingleSubnet" : "MultiSubnet" } } -`, r.setDomainUser(data), data.Locations.Primary, data.RandomInteger, data.RandomString, isSingleSubnet) +`, r.setDomainUser(data), data.RandomInteger, data.RandomString, isSingleSubnet) } func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) configureDomain(data acceptance.TestData) string { diff --git a/internal/services/mssql/mssql_virtual_machine_group_resource.go b/internal/services/mssql/mssql_virtual_machine_group_resource.go index f2fae6edd64b..2bad0209e440 100644 --- a/internal/services/mssql/mssql_virtual_machine_group_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_group_resource.go @@ -8,17 +8,15 @@ import ( "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/location" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/availabilitygrouplisteners" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachinegroups" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/helper" "github.com/hashicorp/terraform-provider-azurerm/internal/services/mssql/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) type MsSqlVirtualMachineGroupResource struct{} @@ -28,10 +26,21 @@ type MsSqlVirtualMachineGroupModel struct { ResourceGroup string `tfschema:"resource_group_name"` Location string `tfschema:"location"` - SqlImageOffer string `tfschema:"sql_image_offer"` - SqlImageSku string `tfschema:"sql_image_sku"` - WsfcDomainProfile []helper.WsfcDomainProfile `tfschema:"wsfc_domain_profile"` - Tags map[string]string `tfschema:"tags"` + SqlImageOffer string `tfschema:"sql_image_offer"` + SqlImageSku string `tfschema:"sql_image_sku"` + WsfcDomainProfile []WsfcDomainProfile `tfschema:"wsfc_domain_profile"` + Tags map[string]string `tfschema:"tags"` +} + +type WsfcDomainProfile struct { + Fqdn string `tfschema:"fqdn"` + OrganizationalUnitPath string `tfschema:"organizational_unit_path"` + ClusterBootstrapAccountName string `tfschema:"cluster_bootstrap_account_name"` + ClusterOperatorAccountName string `tfschema:"cluster_operator_account_name"` + SqlServiceAccountName string `tfschema:"sql_service_account_name"` + StorageAccountUrl string `tfschema:"storage_account_url"` + StorageAccountPrimaryKey string `tfschema:"storage_account_primary_key"` + ClusterSubnetType string `tfschema:"cluster_subnet_type"` } var _ sdk.Resource = MsSqlVirtualMachineGroupResource{} @@ -78,7 +87,73 @@ func (r MsSqlVirtualMachineGroupResource) Arguments() map[string]*pluginsdk.Sche }, false), }, - "wsfc_domain_profile": helper.WsfcDomainProfileSchemaMsSqlVirtualMachineAvailabilityGroup(), + "wsfc_domain_profile": { + Type: pluginsdk.TypeList, + Required: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "cluster_subnet_type": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sqlvirtualmachinegroups.ClusterSubnetTypeMultiSubnet), + string(sqlvirtualmachinegroups.ClusterSubnetTypeSingleSubnet), + }, false), + }, + + "fqdn": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "organizational_unit_path": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "cluster_bootstrap_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "cluster_operator_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "sql_service_account_name": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_account_url": { + Type: pluginsdk.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "storage_account_primary_key": { + Type: pluginsdk.TypeString, + Optional: true, + Sensitive: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, "tags": tags.Schema(), } @@ -105,7 +180,7 @@ func (r MsSqlVirtualMachineGroupResource) Create() sdk.ResourceFunc { existing, err := client.Get(ctx, id) if err != nil { if !response.WasNotFound(existing.HttpResponse) { - return fmt.Errorf("checking for present of existing %s: %+v", id, err) + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) } } if !response.WasNotFound(existing.HttpResponse) { @@ -114,13 +189,13 @@ func (r MsSqlVirtualMachineGroupResource) Create() sdk.ResourceFunc { parameters := sqlvirtualmachinegroups.SqlVirtualMachineGroup{ Properties: &sqlvirtualmachinegroups.SqlVirtualMachineGroupProperties{ - SqlImageOffer: utils.String(model.SqlImageOffer), + SqlImageOffer: pointer.To(model.SqlImageOffer), SqlImageSku: pointer.To(sqlvirtualmachinegroups.SqlVMGroupImageSku(model.SqlImageSku)), WsfcDomainProfile: expandMsSqlVirtualMachineGroupWsfcDomainProfile(model.WsfcDomainProfile), }, - Location: azure.NormalizeLocation(model.Location), - Tags: &model.Tags, + Location: location.Normalize(model.Location), + Tags: pointer.To(model.Tags), } if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { @@ -161,17 +236,8 @@ func (r MsSqlVirtualMachineGroupResource) Read() sdk.ResourceFunc { if model := resp.Model; model != nil { if props := model.Properties; props != nil { - sqlImageOffer := "" - if props.SqlImageOffer != nil { - sqlImageOffer = *props.SqlImageOffer - } - state.SqlImageOffer = sqlImageOffer - - sqlImageSku := "" - if props.SqlImageSku != nil { - sqlImageSku = string(*props.SqlImageSku) - } - state.SqlImageSku = sqlImageSku + state.SqlImageOffer = pointer.From(props.SqlImageOffer) + state.SqlImageSku = string(pointer.From(props.SqlImageSku)) var oldModel MsSqlVirtualMachineGroupModel if err = metadata.Decode(&oldModel); err != nil { @@ -184,10 +250,10 @@ func (r MsSqlVirtualMachineGroupResource) Read() sdk.ResourceFunc { state.WsfcDomainProfile = flattenMsSqlVirtualMachineGroupWsfcDomainProfile(props.WsfcDomainProfile, storageAccountPrimaryKey) } - state.Location = azure.NormalizeLocation(model.Location) + state.Location = location.Normalize(model.Location) if model.Tags != nil { - state.Tags = *model.Tags + state.Tags = pointer.From(model.Tags) } } return metadata.Encode(&state) @@ -216,12 +282,12 @@ func (r MsSqlVirtualMachineGroupResource) Update() sdk.ResourceFunc { parameters := sqlvirtualmachinegroups.SqlVirtualMachineGroup{ Properties: &sqlvirtualmachinegroups.SqlVirtualMachineGroupProperties{ - SqlImageOffer: utils.String(model.SqlImageOffer), + SqlImageOffer: pointer.To(model.SqlImageOffer), SqlImageSku: pointer.To(sqlvirtualmachinegroups.SqlVMGroupImageSku(model.SqlImageSku)), WsfcDomainProfile: expandMsSqlVirtualMachineGroupWsfcDomainProfile(model.WsfcDomainProfile), }, - Location: azure.NormalizeLocation(model.Location), + Location: location.Normalize(model.Location), Tags: &model.Tags, } @@ -253,7 +319,7 @@ func (r MsSqlVirtualMachineGroupResource) Delete() sdk.ResourceFunc { } } -func expandMsSqlVirtualMachineGroupWsfcDomainProfile(wsfcDomainProfile []helper.WsfcDomainProfile) *sqlvirtualmachinegroups.WsfcDomainProfile { +func expandMsSqlVirtualMachineGroupWsfcDomainProfile(wsfcDomainProfile []WsfcDomainProfile) *sqlvirtualmachinegroups.WsfcDomainProfile { if wsfcDomainProfile == nil { return nil } @@ -261,7 +327,7 @@ func expandMsSqlVirtualMachineGroupWsfcDomainProfile(wsfcDomainProfile []helper. result := sqlvirtualmachinegroups.WsfcDomainProfile{ ClusterSubnetType: pointer.To(sqlvirtualmachinegroups.ClusterSubnetType(wsfcDomainProfile[0].ClusterSubnetType)), DomainFqdn: pointer.To(wsfcDomainProfile[0].Fqdn), - OuPath: pointer.To(wsfcDomainProfile[0].OuPath), + OuPath: pointer.To(wsfcDomainProfile[0].OrganizationalUnitPath), ClusterBootstrapAccount: pointer.To(wsfcDomainProfile[0].ClusterBootstrapAccountName), ClusterOperatorAccount: pointer.To(wsfcDomainProfile[0].ClusterOperatorAccountName), SqlServiceAccount: pointer.To(wsfcDomainProfile[0].SqlServiceAccountName), @@ -272,15 +338,15 @@ func expandMsSqlVirtualMachineGroupWsfcDomainProfile(wsfcDomainProfile []helper. return &result } -func flattenMsSqlVirtualMachineGroupWsfcDomainProfile(domainProfile *sqlvirtualmachinegroups.WsfcDomainProfile, storageAccountPrimaryKey string) []helper.WsfcDomainProfile { +func flattenMsSqlVirtualMachineGroupWsfcDomainProfile(domainProfile *sqlvirtualmachinegroups.WsfcDomainProfile, storageAccountPrimaryKey string) []WsfcDomainProfile { if domainProfile == nil { - return []helper.WsfcDomainProfile{} + return []WsfcDomainProfile{} } - return []helper.WsfcDomainProfile{ + return []WsfcDomainProfile{ { Fqdn: pointer.From(domainProfile.DomainFqdn), - OuPath: pointer.From(domainProfile.OuPath), + OrganizationalUnitPath: pointer.From(domainProfile.OuPath), ClusterBootstrapAccountName: pointer.From(domainProfile.ClusterBootstrapAccount), ClusterOperatorAccountName: pointer.From(domainProfile.ClusterOperatorAccount), SqlServiceAccountName: pointer.From(domainProfile.SqlServiceAccount), diff --git a/internal/services/mssql/mssql_virtual_machine_group_resource_test.go b/internal/services/mssql/mssql_virtual_machine_group_resource_test.go index ca1cf57dc118..40aab420bcae 100644 --- a/internal/services/mssql/mssql_virtual_machine_group_resource_test.go +++ b/internal/services/mssql/mssql_virtual_machine_group_resource_test.go @@ -205,7 +205,7 @@ resource "azurerm_mssql_virtual_machine_group" "test" { wsfc_domain_profile { fqdn = "testdomain.com" - ou_path = "OU=test,DC=testdomain,DC=com" + organizational_unit_path = "OU=test,DC=testdomain,DC=com" cluster_bootstrap_account_name = "bootstrapacc%[3]s" cluster_operator_account_name = "opacc%[3]s" sql_service_account_name = "sqlsrvacc%[3]s" diff --git a/internal/services/mssql/mssql_virtual_machine_resource.go b/internal/services/mssql/mssql_virtual_machine_resource.go index 4fafca4ce6ea..df3b9c7ba195 100644 --- a/internal/services/mssql/mssql_virtual_machine_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_resource.go @@ -433,13 +433,12 @@ func resourceMsSqlVirtualMachine() *pluginsdk.Resource { }, "sql_virtual_machine_group_id": { - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: sqlvirtualmachinegroups.ValidateSqlVirtualMachineGroupID, - DiffSuppressFunc: suppress.CaseDifference, + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: sqlvirtualmachinegroups.ValidateSqlVirtualMachineGroupID, }, - "wsfc_domain_credentials": { + "wsfc_domain_credential": { Type: pluginsdk.TypeList, Optional: true, MaxItems: 1, @@ -556,7 +555,7 @@ func resourceMsSqlVirtualMachineCreateUpdate(d *pluginsdk.ResourceData, meta int AutoPatchingSettings: expandSqlVirtualMachineAutoPatchingSettings(d.Get("auto_patching").([]interface{})), AssessmentSettings: expandSqlVirtualMachineAssessmentSettings(d.Get("assessment").([]interface{})), KeyVaultCredentialSettings: expandSqlVirtualMachineKeyVaultCredential(d.Get("key_vault_credential").([]interface{})), - WsfcDomainCredentials: expandSqlVirtualMachineWsfcDomainCredentials(d.Get("wsfc_domain_credentials").([]interface{})), + WsfcDomainCredentials: expandSqlVirtualMachineWsfcDomainCredentials(d.Get("wsfc_domain_credential").([]interface{})), SqlVirtualMachineGroupResourceId: pointer.To(sqlVmGroupId), ServerConfigurationsManagementSettings: &sqlvirtualmachines.ServerConfigurationsManagementSettings{ AdditionalFeaturesServerConfigurations: &sqlvirtualmachines.AdditionalFeaturesServerConfigurations{ @@ -700,15 +699,17 @@ func resourceMsSqlVirtualMachineRead(d *pluginsdk.ResourceData, meta interface{} return fmt.Errorf("setting `storage_configuration`: %+v", err) } - sqlVirtualMachineGroupIdStr := "" + sqlVirtualMachineGroupId := "" if props.SqlVirtualMachineGroupResourceId != nil { - sqlVirtualMachineGroupId, err := sqlvirtualmachines.ParseSqlVirtualMachineGroupIDInsensitively(*props.SqlVirtualMachineGroupResourceId) + parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineGroupIDInsensitively(*props.SqlVirtualMachineGroupResourceId) if err != nil { return err } - sqlVirtualMachineGroupIdStr = sqlVirtualMachineGroupId.ID() + + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 + sqlVirtualMachineGroupId = sqlvirtualmachines.NewSqlVirtualMachineGroupID(id.SubscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineGroupName).ID() } - d.Set("sql_virtual_machine_group_id", sqlVirtualMachineGroupIdStr) + d.Set("sql_virtual_machine_group_id", sqlVirtualMachineGroupId) if err := tags.FlattenAndSet(d, model.Tags); err != nil { return err diff --git a/internal/services/mssql/mssql_virtual_machine_resource_test.go b/internal/services/mssql/mssql_virtual_machine_resource_test.go index bd28433401a2..02aef2930bbf 100644 --- a/internal/services/mssql/mssql_virtual_machine_resource_test.go +++ b/internal/services/mssql/mssql_virtual_machine_resource_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "testing" + "time" "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-sdk/resource-manager/sqlvirtualmachine/2022-02-01/sqlvirtualmachines" @@ -314,6 +315,42 @@ func TestAccMsSqlVirtualMachine_assessmentSettings(t *testing.T) { }) } +func TestAccMsSqlVirtualMachine_sqlVirtualMachineGroup(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_virtual_machine", "test") + r := MsSqlVirtualMachineResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: MsSqlVirtualMachineAvailabilityGroupListenerResource{}.configureDomain(data), + }, + { + PreConfig: func() { time.Sleep(12 * time.Minute) }, + Config: MsSqlVirtualMachineAvailabilityGroupListenerResource{}.setDomainUser(data), + }, + { + Config: r.sqlVirtualMachineGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("wsfc_domain_credential"), + { + Config: r.sqlVirtualMachineGroupRemoved(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.sqlVirtualMachineGroup(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("wsfc_domain_credential"), + }) +} + func (MsSqlVirtualMachineResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := sqlvirtualmachines.ParseSqlVirtualMachineID(state.ID) if err != nil { @@ -1075,3 +1112,133 @@ resource "azurerm_mssql_virtual_machine" "test" { } `, r.template(data)) } + +func (r MsSqlVirtualMachineResource) sqlVirtualMachineGroup(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_virtual_machine" "test" { + virtual_machine_id = azurerm_windows_virtual_machine.client.id + sql_license_type = "PAYG" + sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id + + wsfc_domain_credential { + cluster_bootstrap_account_password = local.admin_password + cluster_operator_account_password = local.admin_password + sql_service_account_password = local.admin_password + } + + depends_on = [ + azurerm_virtual_machine_extension.join_domain + ] +} +`, r.sqlVirtualMachineGroupDependencies(data)) +} +func (r MsSqlVirtualMachineResource) sqlVirtualMachineGroupRemoved(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_mssql_virtual_machine" "test" { + virtual_machine_id = azurerm_windows_virtual_machine.client.id + sql_license_type = "PAYG" +} +`, r.sqlVirtualMachineGroupDependencies(data)) +} + +func (MsSqlVirtualMachineResource) sqlVirtualMachineGroupDependencies(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +resource "azurerm_subnet" "domain_clients" { + name = "domain-clients" + 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" "client" { + name = "acctestnic-client-%[2]d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "primary" + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.domain_clients.id + } +} + +resource "azurerm_windows_virtual_machine" "client" { + name = "acctest-%[3]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + size = "Standard_F2" + admin_username = local.admin_username + admin_password = local.admin_password + custom_data = local.custom_data + + network_interface_ids = [ + azurerm_network_interface.client.id, + ] + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "MicrosoftSQLServer" + offer = "SQL2019-WS2019" + sku = "SQLDEV" + version = "latest" + } +} + +resource "azurerm_virtual_machine_extension" "join_domain" { + name = "join-domain" + virtual_machine_id = azurerm_windows_virtual_machine.client.id + publisher = "Microsoft.Compute" + type = "JsonADDomainExtension" + type_handler_version = "1.3" + + settings = jsonencode({ + Name = local.active_directory_domain_name, + OUPath = "", + User = "${local.active_directory_domain_name}\\${local.admin_username}", + Restart = "true", + Options = "3" + }) + + protected_settings = jsonencode({ + Password = local.admin_password + }) +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%[3]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_mssql_virtual_machine_group" "test" { + name = "acctestgr-%[3]s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sql_image_offer = "SQL2019-WS2019" + sql_image_sku = "Developer" + + wsfc_domain_profile { + fqdn = local.active_directory_domain_name + + cluster_bootstrap_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + cluster_operator_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + sql_service_account_name = "${local.admin_username}@${local.active_directory_domain_name}" + storage_account_url = azurerm_storage_account.test.primary_blob_endpoint + storage_account_primary_key = azurerm_storage_account.test.primary_access_key + cluster_subnet_type = "SingleSubnet" + } +} +`, MsSqlVirtualMachineAvailabilityGroupListenerResource{}.setDomainUser(data), data.RandomInteger, data.RandomString) +} diff --git a/website/docs/r/mssql_virtual_machine.html.markdown b/website/docs/r/mssql_virtual_machine.html.markdown index 161e89aa0c30..fd3230644baf 100644 --- a/website/docs/r/mssql_virtual_machine.html.markdown +++ b/website/docs/r/mssql_virtual_machine.html.markdown @@ -67,6 +67,10 @@ The following arguments are supported: * `assessment` - (Optional) An `assessment` block as defined below. +* `sql_virtual_machine_group_id` - (Optional) The ID of the SQL Virtual Machine Group that the SQL Virtual Machine belongs to. + +* `wsfc_domain_credential` - (Optional) A `wsfc_domain_credential` block as defined below + * `tags` - (Optional) A mapping of tags to assign to the resource. --- @@ -211,6 +215,16 @@ The `schedule` block supports the following: * `start_time` - (Required) What time the assessment will be run. Must be in the format `HH:mm`. +--- + +The `wsfc_domain_credential` block supports the following: + +* `cluster_bootstrap_account_password` - (Required) The account password used for creating cluster. + +* `cluster_operator_account_password` - (Required) The account password used for operating cluster. + +* `sql_service_account_password` - (Required) The account password under which SQL service will run on all participating SQL virtual machines in the cluster. + ## Attributes Reference In addition to the Arguments listed above - the following Attributes are exported: diff --git a/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown index c806b2d61b7f..7ba47b8e9868 100644 --- a/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown +++ b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown @@ -52,7 +52,7 @@ resource "azurerm_mssql_virtual_machine" "example" { sql_license_type = "PAYG" sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.example.id - wsfc_domain_credentials { + wsfc_domain_credential { cluster_bootstrap_account_password = "P@ssw0rd1234!" cluster_operator_account_password = "P@ssw0rd1234!" sql_service_account_password = "P@ssw0rd1234!" @@ -104,9 +104,9 @@ The following arguments are supported: * `name` - (Required) The name which should be used for the Microsoft SQL Virtual Machine Availability Group Listener. Changing this forces a new resource to be created. -* `sql_virtual_machine_group_id` - (Required) ID of the SQL Virtual Machine Group to create the listener. Changing this forces a new resource to be created. +* `sql_virtual_machine_group_id` - (Required) The ID of the SQL Virtual Machine Group to create the listener. Changing this forces a new resource to be created. -* `availability_group_name` - (Optional) Name of the Availability Group. Changing this forces a new resource to be created. +* `availability_group_name` - (Optional) The name of the Availability Group. Changing this forces a new resource to be created. * `load_balancer_configuration` - (Optional) A `load_balancer_configuration` block as defined below. Changing this forces a new resource to be created. @@ -114,7 +114,7 @@ The following arguments are supported: * `multi_subnet_ip_configuration` - (Optional) One or more `multi_subnet_ip_configuration` blocks as defined below. Changing this forces a new resource to be created. -* `port` - (Optional) Port of the listener. Changing this forces a new resource to be created. +* `port` - (Optional) The port of the listener. Changing this forces a new resource to be created. * `replica` - (Optional) One or more `replica` blocks as defined below. Changing this forces a new resource to be created. @@ -126,9 +126,9 @@ A `load_balancer_configuration` block supports the following: * `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. -* `probe_port` - (Required) Probe port of the listener. Changing this forces a new resource to be created. +* `probe_port` - (Required) The probe port of the listener. Changing this forces a new resource to be created. -* `sql_virtual_machine_ids` - (Required) Specifies a list of IDs of the SQL Virtual Machine. Changing this forces a new resource to be created. +* `sql_virtual_machine_ids` - (Required) Specifies a list of SQL Virtual Machine IDs. Changing this forces a new resource to be created. ~> **NOTE:** `sql_virtual_machine_ids` should match with the SQL Virtual Machines specified in `replica`. @@ -138,7 +138,7 @@ A `multi_subnet_ip_configuration` block supports the following: * `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. -* `sql_virtual_machine_id` - (Required) ID of the Sql Virtual Machine. Changing this forces a new resource to be created. +* `sql_virtual_machine_id` - (Required) The ID of the Sql Virtual Machine. Changing this forces a new resource to be created. ~> **NOTE:** `sql_virtual_machine_id` should match with the SQL Virtual Machines specified in `replica`. @@ -154,13 +154,13 @@ A `private_ip_address` block supports the following: A `replica` block supports the following: -* `commit` - (Required) Replica commit mode in availability group. Possible values are `Synchronous_Commit` and `Asynchronous_Commit`. Changing this forces a new resource to be created. +* `commit` - (Required) T replica commit mode for the availability group. Possible values are `Synchronous_Commit` and `Asynchronous_Commit`. Changing this forces a new resource to be created. -* `failover` - (Required) Replica failover mode in availability group. Possible values are `Manual` and `Automatic`. Changing this forces a new resource to be created. +* `failover_mode` - (Required) The replica failover mode for the availability group. Possible values are `Manual` and `Automatic`. Changing this forces a new resource to be created. -* `readable_secondary` - (Required) Replica readable secondary mode in availability group. Possible values are `No`, `Read_Only` and `All`. Changing this forces a new resource to be created. +* `readable_secondary` - (Required) The replica readable secondary mode for the availability group. Possible values are `No`, `Read_Only` and `All`. Changing this forces a new resource to be created. -* `role` - (Required) Replica Role in availability group. Possible values are `Primary` and `Secondary`. Changing this forces a new resource to be created. +* `role` - (Required) The replica role for the availability group. Possible values are `Primary` and `Secondary`. Changing this forces a new resource to be created. * `sql_virtual_machine_id` - (Required) The ID of the SQL Virtual Machine. Changing this forces a new resource to be created. diff --git a/website/docs/r/mssql_virtual_machine_group.html.markdown b/website/docs/r/mssql_virtual_machine_group.html.markdown index 04998db69102..025343931f57 100644 --- a/website/docs/r/mssql_virtual_machine_group.html.markdown +++ b/website/docs/r/mssql_virtual_machine_group.html.markdown @@ -55,19 +55,19 @@ The following arguments are supported: A `wsfc_domain_profile` block supports the following: -* `cluster_subnet_type` - (Required) Subnet type of the SQL Virtual Machine cluster. Possible values are `MultiSubnet` and `SingleSubnet`. Changing this forces a new resource to be created. +* `cluster_subnet_type` - (Required) The subnet type of the SQL Virtual Machine cluster. Possible values are `MultiSubnet` and `SingleSubnet`. Changing this forces a new resource to be created. -* `fqdn` - (Required) Fully qualified name of the domain. Changing this forces a new resource to be created. +* `fqdn` - (Required) The fully qualified name of the domain. Changing this forces a new resource to be created. -* `cluster_bootstrap_account_name` - (Optional) Account name used for creating cluster. Changing this forces a new resource to be created. +* `cluster_bootstrap_account_name` - (Optional) The account name used for creating cluster. Changing this forces a new resource to be created. -* `cluster_operator_account_name` - (Optional) Account name used for operating cluster. Changing this forces a new resource to be created. +* `cluster_operator_account_name` - (Optional) The account name used for operating cluster. Changing this forces a new resource to be created. -* `ou_path` - (Optional) Organizational Unit path in which the nodes and cluster will be present. Changing this forces a new resource to be created. +* `organizational_unit_path` - (Optional) The organizational Unit path in which the nodes and cluster will be present. Changing this forces a new resource to be created. -* `sql_service_account_name` - (Optional) Account name under which SQL service will run on all participating SQL virtual machines in the cluster. Changing this forces a new resource to be created. +* `sql_service_account_name` - (Optional) The account name under which SQL service will run on all participating SQL virtual machines in the cluster. Changing this forces a new resource to be created. -* `storage_account_primary_key` - (Optional) Primary key of the Storage Account. +* `storage_account_primary_key` - (Optional) The primary key of the Storage Account. * `storage_account_url` - (Optional) The SAS URL to the Storage Container of the witness storage account. Changing this forces a new resource to be created. From 395f7fddd96f8d74fd1e881e7b736e98d1ce0dc9 Mon Sep 17 00:00:00 2001 From: Yichun Ma Date: Mon, 14 Aug 2023 16:52:23 +0800 Subject: [PATCH 4/5] flatten private_ip_address and update doc --- ...ne_availability_group_listener_resource.go | 194 ++++++------------ ...ailability_group_listener_resource_test.go | 25 +-- ..._availability_group_listener.html.markdown | 29 +-- 3 files changed, 80 insertions(+), 168 deletions(-) diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go index ec3da23da21e..7fd15d755c9e 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go @@ -39,20 +39,17 @@ type MsSqlVirtualMachineAvailabilityGroupListenerModel struct { } type LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { - PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` - LoadBalancerId string `tfschema:"load_balancer_id"` - ProbePort int `tfschema:"probe_port"` - SqlVirtualMachineIds []string `tfschema:"sql_virtual_machine_ids"` + LoadBalancerId string `tfschema:"load_balancer_id"` + PrivateIpAddress string `tfschema:"private_ip_address"` + ProbePort int `tfschema:"probe_port"` + SqlVirtualMachineIds []string `tfschema:"sql_virtual_machine_ids"` + SubnetId string `tfschema:"subnet_id"` } type MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener struct { - PrivateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener `tfschema:"private_ip_address"` - SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` -} - -type PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener struct { - IpAddress string `tfschema:"ip_address"` - SubnetId string `tfschema:"subnet_id"` + PrivateIpAddress string `tfschema:"private_ip_address"` + SqlVirtualMachineId string `tfschema:"sql_virtual_machine_id"` + SubnetId string `tfschema:"subnet_id"` } type ReplicaMsSqlVirtualMachineAvailabilityGroupListener struct { @@ -114,30 +111,6 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st MaxItems: 1, Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ - "private_ip_address": { - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "ip_address": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.IsIPAddress, - }, - - "subnet_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: networkValidate.SubnetID, - }, - }, - }, - }, - "load_balancer_id": { Type: pluginsdk.TypeString, Required: true, @@ -145,6 +118,13 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st ValidateFunc: lbValidate.LoadBalancerID, }, + "private_ip_address": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.IsIPAddress, + }, + "probe_port": { Type: pluginsdk.TypeInt, Required: true, @@ -161,6 +141,13 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, }, }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, }, }, }, @@ -173,27 +160,10 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st Elem: &pluginsdk.Resource{ Schema: map[string]*pluginsdk.Schema{ "private_ip_address": { - Type: pluginsdk.TypeList, - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "ip_address": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.IsIPAddress, - }, - - "subnet_id": { - Type: pluginsdk.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: networkValidate.SubnetID, - }, - }, - }, + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.IsIPAddress, }, "sql_virtual_machine_id": { @@ -202,6 +172,13 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Arguments() map[st ForceNew: true, ValidateFunc: sqlvirtualmachines.ValidateSqlVirtualMachineID, }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: networkValidate.SubnetID, + }, }, }, }, @@ -437,13 +414,11 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration } lbConfig.SqlVirtualMachineInstances = utils.ExpandStringSlice(parsedIds) - if lb.PrivateIpAddress != nil { - privateIpAddress, err := expandMsSqlVirtualMachinePrivateIpAddress(lb.PrivateIpAddress) - if err != nil { - return nil, err - } - lbConfig.PrivateIPAddress = privateIpAddress + lbConfig.PrivateIPAddress = &availabilitygrouplisteners.PrivateIPAddress{ + IPAddress: pointer.To(lb.PrivateIpAddress), + SubnetResourceId: pointer.To(lb.SubnetId), } + results = append(results, lbConfig) } return &results, nil @@ -458,43 +433,16 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguratio SqlVirtualMachineInstance: item.SqlVirtualMachineId, } - if item.PrivateIpAddress != nil { - privateIpAddress, err := expandMsSqlVirtualMachinePrivateIpAddress(item.PrivateIpAddress) - if err != nil { - return nil, err - } - config.PrivateIPAddress = *privateIpAddress + config.PrivateIPAddress = availabilitygrouplisteners.PrivateIPAddress{ + IPAddress: pointer.To(item.PrivateIpAddress), + SubnetResourceId: pointer.To(item.SubnetId), } + results = append(results, config) } return &results, nil } -func expandMsSqlVirtualMachinePrivateIpAddress(input []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener) (*availabilitygrouplisteners.PrivateIPAddress, error) { - if len(input) == 0 { - return nil, nil - } - - var ipAddress, subnetId string - if input[0].IpAddress != "" { - ipAddress = input[0].IpAddress - } - - if input[0].SubnetId != "" { - id, err := networkParse.SubnetID(input[0].SubnetId) - if err != nil { - return nil, err - } - subnetId = id.ID() - } - - return &availabilitygrouplisteners.PrivateIPAddress{ - IPAddress: pointer.To(ipAddress), - - SubnetResourceId: pointer.To(subnetId), - }, nil -} - func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(input *[]availabilitygrouplisteners.LoadBalancerConfiguration, subscriptionId string) ([]LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) { results := make([]LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, 0) if input == nil || len(*input) == 0 { @@ -502,14 +450,16 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio } for _, lbConfig := range *input { + privateIpAddress := "" + subnetResourceId := "" + if v := lbConfig.PrivateIPAddress; v != nil { + privateIpAddress = pointer.From(v.IPAddress) - var privateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener - if lbConfig.PrivateIPAddress != nil { - flattenedPrivateIp, err := flattenPrivateIpAddress(*lbConfig.PrivateIPAddress) + parsedSubnetResourceId, err := networkParse.SubnetIDInsensitively(pointer.From(v.SubnetResourceId)) if err != nil { return nil, err } - privateIpAddress = flattenedPrivateIp + subnetResourceId = parsedSubnetResourceId.ID() } loadBalancerId := "" @@ -527,22 +477,24 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguratio var parsedIds []string for _, sqlVmId := range sqlVirtualMachineIds { parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(sqlVmId) - - // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 - newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) if err != nil { return nil, err } + + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 + newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) + parsedIds = append(parsedIds, newId.ID()) } sqlVirtualMachineIds = parsedIds } v := LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ - PrivateIpAddress: privateIpAddress, LoadBalancerId: loadBalancerId, + PrivateIpAddress: privateIpAddress, ProbePort: int(pointer.From(lbConfig.ProbePort)), SqlVirtualMachineIds: sqlVirtualMachineIds, + SubnetId: subnetResourceId, } results = append(results, v) @@ -557,24 +509,23 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfigurati } for _, config := range *input { - var privateIpAddress []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener - flattenedPrivateIp, err := flattenPrivateIpAddress(config.PrivateIPAddress) + parsedSubnetResourceId, err := networkParse.SubnetIDInsensitively(pointer.From(config.PrivateIPAddress.SubnetResourceId)) if err != nil { return nil, err } - privateIpAddress = flattenedPrivateIp - - parsedId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(config.SqlVirtualMachineInstance) - // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 - newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) + parsedSqlVirtualMachineId, err := sqlvirtualmachines.ParseSqlVirtualMachineIDInsensitively(config.SqlVirtualMachineInstance) if err != nil { return nil, err } + // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 + newSqlVirtualMachineId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedSqlVirtualMachineId.ResourceGroupName, parsedSqlVirtualMachineId.SqlVirtualMachineName) + v := MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener{ - PrivateIpAddress: privateIpAddress, - SqlVirtualMachineId: newId.ID(), + PrivateIpAddress: pointer.From(config.PrivateIPAddress.IPAddress), + SqlVirtualMachineId: newSqlVirtualMachineId.ID(), + SubnetId: parsedSubnetResourceId.ID(), } results = append(results, v) @@ -582,26 +533,6 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfigurati return results, nil } -func flattenPrivateIpAddress(input availabilitygrouplisteners.PrivateIPAddress) ([]PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener, error) { - - privateIpAddress := PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{ - IpAddress: pointer.From(input.IPAddress), - } - - subnetId := "" - if input.SubnetResourceId != nil { - id, err := networkParse.SubnetIDInsensitively(*input.SubnetResourceId) - if err != nil { - return nil, err - } - subnetId = id.ID() - } - - privateIpAddress.SubnetId = subnetId - - return []PrivateIpAddressMsSqlVirtualMachineAvailabilityGroupListener{privateIpAddress}, nil -} - func expandMsSqlVirtualMachineAvailabilityGroupListenerReplicas(replicas []ReplicaMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.AgReplica, error) { results := make([]availabilitygrouplisteners.AgReplica, 0) @@ -645,9 +576,6 @@ func flattenMsSqlVirtualMachineAvailabilityGroupListenerReplicas(input *[]availa // get correct casing for subscription in id due to https://github.com/Azure/azure-rest-api-specs/issues/25211 newId := sqlvirtualmachines.NewSqlVirtualMachineID(subscriptionId, parsedId.ResourceGroupName, parsedId.SqlVirtualMachineName) - if err != nil { - return nil, err - } sqlVirtualMachineInstanceId = newId.ID() } diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go index 2f95b227f57e..6f6e1f364361 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource_test.go @@ -111,13 +111,10 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id load_balancer_configuration { - load_balancer_id = azurerm_lb.test.id - probe_port = 51572 - - private_ip_address { - ip_address = "10.0.2.11" - subnet_id = azurerm_subnet.domain_clients[0].id - } + load_balancer_id = azurerm_lb.test.id + private_ip_address = "10.0.2.11" + probe_port = 51572 + subnet_id = azurerm_subnet.domain_clients[0].id sql_virtual_machine_ids = [ azurerm_mssql_virtual_machine.test[0].id, @@ -155,21 +152,15 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "test" { sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.test.id multi_subnet_ip_configuration { - private_ip_address { - ip_address = "10.0.2.11" - subnet_id = azurerm_subnet.domain_clients[0].id - } - + private_ip_address = "10.0.2.11" sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[0].id + subnet_id = azurerm_subnet.domain_clients[0].id } multi_subnet_ip_configuration { - private_ip_address { - ip_address = "10.0.3.11" - subnet_id = azurerm_subnet.domain_clients[1].id - } - + private_ip_address = "10.0.3.11" sql_virtual_machine_id = azurerm_mssql_virtual_machine.test[1].id + subnet_id = azurerm_subnet.domain_clients[1].id } replica { diff --git a/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown index 7ba47b8e9868..2b9170e48509 100644 --- a/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown +++ b/website/docs/r/mssql_virtual_machine_availability_group_listener.html.markdown @@ -66,13 +66,10 @@ resource "azurerm_mssql_virtual_machine_availability_group_listener" "example" { sql_virtual_machine_group_id = azurerm_mssql_virtual_machine_group.example.id load_balancer_configuration { - load_balancer_id = data.azurerm_lb.example.id - probe_port = 51572 - - private_ip_address { - ip_address = "10.0.2.11" - subnet_id = data.azurerm_subnet.example.id - } + load_balancer_id = data.azurerm_lb.example.id + private_ip_address = "10.0.2.11" + probe_port = 51572 + subnet_id = data.azurerm_subnet.example.id sql_virtual_machine_ids = [ azurerm_mssql_virtual_machine.example[0].id, @@ -124,37 +121,33 @@ A `load_balancer_configuration` block supports the following: * `load_balancer_id` - (Required) The ID of the Load Balancer. Changing this forces a new resource to be created. -* `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. +* `private_ip_address` - (Required) The private IP Address of the listener. Changing this forces a new resource to be created. * `probe_port` - (Required) The probe port of the listener. Changing this forces a new resource to be created. * `sql_virtual_machine_ids` - (Required) Specifies a list of SQL Virtual Machine IDs. Changing this forces a new resource to be created. +* `subnet_id` - (Required) The ID of the Subnet to create the listener. Changing this forces a new resource to be created. + ~> **NOTE:** `sql_virtual_machine_ids` should match with the SQL Virtual Machines specified in `replica`. --- A `multi_subnet_ip_configuration` block supports the following: -* `private_ip_address` - (Required) A `private_ip_address` block as defined below. Changing this forces a new resource to be created. +* `private_ip_address` - (Required) The private IP Address of the listener. Changing this forces a new resource to be created. * `sql_virtual_machine_id` - (Required) The ID of the Sql Virtual Machine. Changing this forces a new resource to be created. -~> **NOTE:** `sql_virtual_machine_id` should match with the SQL Virtual Machines specified in `replica`. - ---- - -A `private_ip_address` block supports the following: +* `subnet_id` - (Required) The ID of the Subnet to create the listener. Changing this forces a new resource to be created. -* `ip_address` - (Required) IP Address. Changing this forces a new resource to be created. - -* `subnet_id` - (Required) The ID of the Subnet. Changing this forces a new resource to be created. +~> **NOTE:** `sql_virtual_machine_id` should match with the SQL Virtual Machines specified in `replica`. --- A `replica` block supports the following: -* `commit` - (Required) T replica commit mode for the availability group. Possible values are `Synchronous_Commit` and `Asynchronous_Commit`. Changing this forces a new resource to be created. +* `commit` - (Required) The replica commit mode for the availability group. Possible values are `Synchronous_Commit` and `Asynchronous_Commit`. Changing this forces a new resource to be created. * `failover_mode` - (Required) The replica failover mode for the availability group. Possible values are `Manual` and `Automatic`. Changing this forces a new resource to be created. From 036042b0175d7d23737ef3ea414e37d81594827f Mon Sep 17 00:00:00 2001 From: Yichun Ma Date: Mon, 14 Aug 2023 17:03:39 +0800 Subject: [PATCH 5/5] fix lint --- ...al_machine_availability_group_listener_resource.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go index 7fd15d755c9e..abc4deb0dd94 100644 --- a/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go +++ b/internal/services/mssql/mssql_virtual_machine_availability_group_listener_resource.go @@ -288,11 +288,7 @@ func (r MsSqlVirtualMachineAvailabilityGroupListenerResource) Create() sdk.Resou } if model.MultiSubnetIpConfiguration != nil && len(model.MultiSubnetIpConfiguration) != 0 { - multiSubnetIpConfiguration, err := expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(model.MultiSubnetIpConfiguration) - if err != nil { - return err - } - parameters.Properties.MultiSubnetIPConfigurations = multiSubnetIpConfiguration + parameters.Properties.MultiSubnetIPConfigurations = expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(model.MultiSubnetIpConfiguration) } if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { @@ -424,7 +420,7 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfiguration return &results, nil } -func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(multiSubnetIpConfiguration []MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener) (*[]availabilitygrouplisteners.MultiSubnetIPConfiguration, error) { +func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguration(multiSubnetIpConfiguration []MultiSubnetIpConfigurationMsSqlVirtualMachineAvailabilityGroupListener) *[]availabilitygrouplisteners.MultiSubnetIPConfiguration { results := make([]availabilitygrouplisteners.MultiSubnetIPConfiguration, 0) for _, item := range multiSubnetIpConfiguration { @@ -440,7 +436,8 @@ func expandMsSqlVirtualMachineAvailabilityGroupListenerMultiSubnetIpConfiguratio results = append(results, config) } - return &results, nil + + return &results } func flattenMsSqlVirtualMachineAvailabilityGroupListenerLoadBalancerConfigurations(input *[]availabilitygrouplisteners.LoadBalancerConfiguration, subscriptionId string) ([]LoadBalancerConfigurationMsSqlVirtualMachineAvailabilityGroupListener, error) {