Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_mssql_database - support for the import property. #18588

Merged
merged 3 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions internal/services/mssql/mssql_database_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/maintenance/2021-05-01/publicmaintenanceconfigurations"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand Down Expand Up @@ -253,6 +254,9 @@ func resourceMsSqlDatabaseCreateUpdate(d *pluginsdk.ResourceData, meta interface
if _, dbok := d.GetOk("restore_dropped_database_id"); ok && createMode.(string) == string(sql.CreateModeRestore) && !dbok {
return fmt.Errorf("'restore_dropped_database_id' is required for create_mode %s", createMode.(string))
}
if _, dbok := d.GetOk("import"); ok && createMode.(string) != string(sql.CreateModeDefault) && dbok {
return fmt.Errorf("import can only be used when create_mode is Default")
}

params.DatabaseProperties.CreateMode = sql.CreateMode(createMode.(string))

Expand Down Expand Up @@ -381,6 +385,18 @@ func resourceMsSqlDatabaseCreateUpdate(d *pluginsdk.ResourceData, meta interface
}
}

if _, ok := d.GetOk("import"); ok {
importParameters := expandMsSqlServerImport(d)
importFuture, err := client.Import(ctx, id.ResourceGroup, id.ServerName, id.Name, importParameters)
if err != nil {
return fmt.Errorf("while import bacpac into the new database %s (Resource Group %s): %+v", id.Name, id.ResourceGroup, err)
}

if err = importFuture.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("while import bacpac into the new database %s (Resource Group %s): %+v", id.Name, id.ResourceGroup, err)
}
}

d.SetId(id.ID())

// For datawarehouse SKUs only
Expand Down Expand Up @@ -723,6 +739,28 @@ func expandMsSqlServerSecurityAlertPolicy(d *pluginsdk.ResourceData) sql.Databas
return policy
}

func expandMsSqlServerImport(d *pluginsdk.ResourceData) (out sql.ImportExistingDatabaseDefinition) {
v := d.Get("import")
dbImportRefs := v.([]interface{})
dbImportRef := dbImportRefs[0].(map[string]interface{})
out = sql.ImportExistingDatabaseDefinition{
StorageKeyType: sql.StorageKeyType(dbImportRef["storage_key_type"].(string)),
StorageKey: utils.String(dbImportRef["storage_key"].(string)),
StorageURI: utils.String(dbImportRef["storage_uri"].(string)),
AdministratorLogin: utils.String(dbImportRef["administrator_login"].(string)),
AdministratorLoginPassword: utils.String(dbImportRef["administrator_login_password"].(string)),
AuthenticationType: utils.String(dbImportRef["authentication_type"].(string)),
}

if storageAccountId, ok := d.GetOk("storage_account_id"); ok {
out.NetworkIsolation = &sql.NetworkIsolationSettings{
StorageAccountResourceID: utils.String(storageAccountId.(string)),
SQLServerResourceID: utils.String(d.Get("server_id").(string)),
}
}
return
}

func resourceMsSqlDatabaseMaintenanceNames() []string {
return []string{"SQL_Default", "SQL_EastUS_DB_1", "SQL_EastUS2_DB_1", "SQL_SoutheastAsia_DB_1", "SQL_AustraliaEast_DB_1", "SQL_NorthEurope_DB_1", "SQL_SouthCentralUS_DB_1", "SQL_WestUS2_DB_1",
"SQL_UKSouth_DB_1", "SQL_WestEurope_DB_1", "SQL_EastUS_DB_2", "SQL_EastUS2_DB_2", "SQL_WestUS2_DB_2", "SQL_SoutheastAsia_DB_2", "SQL_AustraliaEast_DB_2", "SQL_NorthEurope_DB_2", "SQL_SouthCentralUS_DB_2",
Expand Down Expand Up @@ -775,6 +813,54 @@ func resourceMsSqlDatabaseSchema() map[string]*pluginsdk.Schema {
string(sql.CreateModeSecondary),
}, false),
},
"import": {
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"storage_uri": {
Type: pluginsdk.TypeString,
Required: true,
},
"storage_key": {
Type: pluginsdk.TypeString,
Required: true,
Sensitive: true,
},
"storage_key_type": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
string(sql.StorageKeyTypeSharedAccessKey),
string(sql.StorageKeyTypeStorageAccessKey),
}, false),
},
"administrator_login": {
Type: pluginsdk.TypeString,
Required: true,
},
"administrator_login_password": {
katbyte marked this conversation as resolved.
Show resolved Hide resolved
Type: pluginsdk.TypeString,
Required: true,
Sensitive: true,
},
"authentication_type": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"ADPassword",
"Sql",
}, false),
},
"storage_account_id": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: azure.ValidateResourceID,
},
},
},
},

"collation": {
Type: pluginsdk.TypeString,
Expand Down
68 changes: 68 additions & 0 deletions internal/services/mssql/mssql_database_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,20 @@ func TestAccMsSqlDatabase_ledgerEnabled(t *testing.T) {
})
}

func TestAccMsSqlDatabase_bacpac(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_mssql_database", "test")
r := MsSqlDatabaseResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.bacpac(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
})
}

func (MsSqlDatabaseResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.DatabaseID(state.ID)
if err != nil {
Expand Down Expand Up @@ -1506,3 +1520,57 @@ resource "azurerm_mssql_database" "test" {
}
`, r.template(data), data.RandomInteger)
}

func (r MsSqlDatabaseResource) bacpac(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s

resource "azurerm_storage_account" "test" {
name = "accsa%d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_storage_container" "test" {
name = "bacpac"
storage_account_name = azurerm_storage_account.test.name
container_access_type = "private"
}

resource "azurerm_storage_blob" "test" {
name = "test.bacpac"
storage_account_name = azurerm_storage_account.test.name
storage_container_name = azurerm_storage_container.test.name
type = "Block"
source = "testdata/sql_import.bacpac"
}

resource "azurerm_sql_firewall_rule" "test" {
name = "allowazure"
resource_group_name = azurerm_resource_group.test.name
server_name = azurerm_mssql_server.test.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}

resource "azurerm_mssql_database" "test" {
name = "acctest-db-%[2]d"
server_id = azurerm_mssql_server.test.id

import {
storage_uri = azurerm_storage_blob.test.url
storage_key = azurerm_storage_account.test.primary_access_key
storage_key_type = "StorageAccessKey"
administrator_login = azurerm_mssql_server.test.administrator_login
administrator_login_password = azurerm_mssql_server.test.administrator_login_password
authentication_type = "Sql"
}

timeouts {
create = "10h"
}
}
`, r.template(data), data.RandomInteger)
}
Binary file not shown.
14 changes: 14 additions & 0 deletions website/docs/r/mssql_database.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ The following arguments are supported:

* `create_mode` - (Optional) The create mode of the database. Possible values are `Copy`, `Default`, `OnlineSecondary`, `PointInTimeRestore`, `Recovery`, `Restore`, `RestoreExternalBackup`, `RestoreExternalBackupSecondary`, `RestoreLongTermRetentionBackup` and `Secondary`.

* `import` - (Optional) A Database Import block as documented below. `create_mode` must be set to `Default`.

* `creation_source_database_id` - (Optional) The ID of the source database from which to create the new database. This should only be used for databases with `create_mode` values that use another database as reference. Changing this forces a new resource to be created.

-> **Note:** When configuring a secondary database, please be aware of the constraints for the `sku_name` property, as noted below, for both the primary and secondary databases. The `sku_name` of the secondary database may be inadvertently changed to match that of the primary when an incompatible combination of SKUs is detected by the provider.
Expand Down Expand Up @@ -125,6 +127,18 @@ The following arguments are supported:

* `tags` - (Optional) A mapping of tags to assign to the resource.

---
a `import` block supports the following:

* `storage_uri` - (Required) Specifies the blob URI of the .bacpac file.
* `storage_key` - (Required) Specifies the access key for the storage account.
* `storage_key_type` - (Required) Specifies the type of access key for the storage account. Valid values are `StorageAccessKey` or `SharedAccessKey`.
* `administrator_login` - (Required) Specifies the name of the SQL administrator.
* `administrator_login_password` - (Required) Specifies the password of the SQL administrator.
* `authentication_type` - (Required) Specifies the type of authentication used to access the server. Valid values are `SQL` or `ADPassword`.
* `storage_account_id` - (Optional) The resource id for the storage account used to store BACPAC file. If set, private endpoint connection will be created for the storage account. Must match storage account used for storage_uri parameter.


---
a `threat_detection_policy` block supports the following:

Expand Down