diff --git a/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource.go b/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource.go index 792db2b98d45..71a48853a4a4 100644 --- a/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource.go +++ b/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource.go @@ -140,7 +140,6 @@ func (r MsSqlManagedInstanceResource) Arguments() map[string]*pluginsdk.Schema { "subnet_id": { Type: schema.TypeString, Required: true, - ForceNew: true, ValidateFunc: commonids.ValidateSubnetID, }, @@ -181,7 +180,7 @@ func (r MsSqlManagedInstanceResource) Arguments() map[string]*pluginsdk.Schema { ValidateFunc: validate.ManagedInstanceID, }, - "identity": commonschema.SystemOrUserAssignedIdentityOptional(), + "identity": commonschema.SystemAssignedUserAssignedIdentityOptional(), "maintenance_configuration_name": { Type: schema.TypeString, @@ -418,6 +417,9 @@ func (r MsSqlManagedInstanceResource) Update() sdk.ResourceFunc { RequestedBackupStorageRedundancy: pointer.To(storageAccTypeToBackupStorageRedundancy(state.StorageAccountType)), VCores: pointer.To(state.VCores), ZoneRedundant: pointer.To(state.ZoneRedundantEnabled), + AdministratorLogin: pointer.To(state.AdministratorLogin), + AdministratorLoginPassword: pointer.To(state.AdministratorLoginPassword), + SubnetId: pointer.To(state.SubnetId), }, Tags: pointer.To(state.Tags), } diff --git a/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource_test.go b/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource_test.go index 1584a010d8a4..275f9f9af4e5 100644 --- a/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource_test.go +++ b/internal/services/mssqlmanagedinstance/mssql_managed_instance_resource_test.go @@ -146,6 +146,24 @@ func TestAccMsSqlManagedInstance_identity(t *testing.T) { }) } +func TestAccMsSqlManagedInstance_systemAssignedUserAssignedIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_managed_instance", "test") + r := MsSqlManagedInstanceResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.systemAndUserIdentity(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("identity.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.identity_ids.#").HasValue("1"), + check.That(data.ResourceName).Key("identity.0.type").HasValue("SystemAssigned, UserAssigned"), + ), + }, + data.ImportStep("administrator_login_password"), + }) +} + func TestAccMsSqlManagedInstance_multiple(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mssql_managed_instance", "test") r := MsSqlManagedInstanceResource{} @@ -294,6 +312,28 @@ func TestAccMsSqlManagedInstance_backupRedundancyUpdated(t *testing.T) { }) } +func TestAccMsSqlManagedInstance_subnetUpdate(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mssql_managed_instance", "test") + r := MsSqlManagedInstanceResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("administrator_login_password"), + { + Config: r.subnetUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep("administrator_login_password"), + }) +} + func (r MsSqlManagedInstanceResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := commonids.ParseSqlManagedInstanceID(state.ID) if err != nil { @@ -532,6 +572,62 @@ resource "azurerm_mssql_managed_instance" "test" { `, r.template(data, data.Locations.Primary), data.RandomInteger) } +func (r MsSqlManagedInstanceResource) systemAndUserIdentity(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +provider "azurerm" { + features { + resource_group { + /* Due to the creation of unmanaged Microsoft.Network/networkIntentPolicies in this service, + prevent_deletion_if_contains_resources has been added here to allow the test resources to be + deleted until this can be properly investigated + */ + prevent_deletion_if_contains_resources = false + } + } +} + +resource "azurerm_user_assigned_identity" "test" { + location = azurerm_resource_group.test.location + name = "acctestsqlserver%[2]d" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_mssql_managed_instance" "test" { + name = "acctestsqlserver%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + license_type = "BasePrice" + sku_name = "GP_Gen5" + storage_size_in_gb = 32 + subnet_id = azurerm_subnet.test.id + vcores = 4 + + administrator_login = "missadministrator" + administrator_login_password = "NCC-1701-D" + + depends_on = [ + azurerm_subnet_network_security_group_association.test, + azurerm_subnet_route_table_association.test, + ] + + identity { + type = "SystemAssigned, UserAssigned" + identity_ids = [ + azurerm_user_assigned_identity.test.id + ] + } + + tags = { + environment = "staging" + database = "test" + } +} +`, r.template(data, data.Locations.Primary), data.RandomInteger) +} + func (r MsSqlManagedInstanceResource) update(data acceptance.TestData) string { return fmt.Sprintf(` %[1]s @@ -1686,3 +1782,75 @@ resource "azurerm_mssql_managed_instance" "test" { } `, r.template(data, data.Locations.Primary), data.RandomInteger) } + +func (r MsSqlManagedInstanceResource) subnetUpdate(data acceptance.TestData) string { + return fmt.Sprintf(` +%[1]s + +provider "azurerm" { + features { + resource_group { + /* Due to the creation of unmanaged Microsoft.Network/networkIntentPolicies in this service, + prevent_deletion_if_contains_resources has been added here to allow the test resources to be + deleted until this can be properly investigated + */ + prevent_deletion_if_contains_resources = false + } + } +} + + +resource "azurerm_subnet" "test2" { + name = "acctestsubnet2-%[2]d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefixes = ["10.0.1.0/24"] + + delegation { + name = "managedinstancedelegation" + + service_delegation { + name = "Microsoft.Sql/managedInstances" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action"] + } + } +} + +resource "azurerm_subnet_route_table_association" "test2" { + subnet_id = azurerm_subnet.test2.id + route_table_id = azurerm_route_table.test.id +} + +resource "azurerm_subnet_network_security_group_association" "test2" { + subnet_id = azurerm_subnet.test2.id + network_security_group_id = azurerm_network_security_group.test.id +} + +resource "azurerm_mssql_managed_instance" "test" { + name = "acctestsqlserver%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + license_type = "BasePrice" + sku_name = "GP_Gen5" + storage_size_in_gb = 32 + subnet_id = azurerm_subnet.test.id + vcores = 4 + + administrator_login = "missadministrator" + administrator_login_password = "NCC-1701-D" + + depends_on = [ + azurerm_subnet_network_security_group_association.test, + azurerm_subnet_route_table_association.test, + azurerm_subnet_network_security_group_association.test2, + azurerm_subnet_route_table_association.test2, + ] + + tags = { + environment = "staging" + database = "test" + } +} +`, r.template(data, data.Locations.Primary), data.RandomInteger) +} diff --git a/website/docs/r/mssql_managed_instance.html.markdown b/website/docs/r/mssql_managed_instance.html.markdown index 4e30add4fdc0..e85b59c84d6b 100644 --- a/website/docs/r/mssql_managed_instance.html.markdown +++ b/website/docs/r/mssql_managed_instance.html.markdown @@ -223,7 +223,7 @@ The following arguments are supported: * `storage_size_in_gb` - (Required) Maximum storage space for the SQL Managed instance. This should be a multiple of 32 (GB). -* `subnet_id` - (Required) The subnet resource id that the SQL Managed Instance will be associated with. Changing this forces a new resource to be created. +* `subnet_id` - (Required) The subnet resource id that the SQL Managed Instance will be associated with. * `vcores` - (Required) Number of cores that should be assigned to the SQL Managed Instance. Values can be `8`, `16`, or `24` for Gen4 SKUs, or `4`, `6`, `8`, `10`, `12`, `16`, `20`, `24`, `32`, `40`, `48`, `56`, `64`, `80`, `96` or `128` for Gen5 SKUs. @@ -255,9 +255,9 @@ The following arguments are supported: An `identity` block supports the following: -* `type` - (Required) Specifies the type of Managed Service Identity that should be configured on this SQL Managed Instance. Possible values are `SystemAssigned`, `UserAssigned`. +* `type` - (Required) Specifies the type of Managed Service Identity that should be configured on this SQL Managed Instance. Possible values are `SystemAssigned`, `UserAssigned`, `SystemAssigned, UserAssigned`. -* `identity_ids` - (Optional) Specifies a list of User Assigned Managed Identity IDs to be assigned to this SQL Managed Instance. Required when `type` is set to `UserAssigned`. +* `identity_ids` - (Optional) Specifies a list of User Assigned Managed Identity IDs to be assigned to this SQL Managed Instance. Required when `type` includes `UserAssigned`. ~> The assigned `principal_id` and `tenant_id` can be retrieved after the identity `type` has been set to `SystemAssigned` and SQL Managed Instance has been created.