From e552a59647ca3761c9d528e1a3cc3a03e7a4b4e4 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Tue, 13 Mar 2018 06:26:08 +0000 Subject: [PATCH 1/6] add database_import property --- azurerm/resource_arm_sql_database.go | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 91982d81baad..8dfd26b4f829 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -57,6 +57,53 @@ func resourceArmSqlDatabase() *schema.Resource { DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, + "database_import": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "storage_uri": { + Type: schema.TypeString, + Required: true, + }, + "storage_key": { + Type: schema.TypeString, + Required: true, + }, + "storage_key_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "StorageAccessKey", "SharedAccessKey", + }, true), + }, + "administrator_login": { + Type: schema.TypeString, + Required: true, + }, + "administrator_login_password": { + Type: schema.TypeString, + Required: true, + }, + "authentication_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "SQL", "ADPassword", + }, true), + }, + "operation_mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Import", + }, true), + }, + }, + }, + }, + "source_database_id": { Type: schema.TypeString, Optional: true, From e18d1606e25fa8b06e13c9e0b9d2700b05ff4b4f Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Tue, 13 Mar 2018 15:15:22 +0000 Subject: [PATCH 2/6] add option to import database from bacpac --- azurerm/resource_arm_sql_database.go | 40 +++++++++++++++++++++++ website/docs/r/sql_database.html.markdown | 12 +++++++ 2 files changed, 52 insertions(+) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 8dfd26b4f829..a03f21618280 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/sql/mgmt/2015-05-01-preview/sql" @@ -284,6 +285,27 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} return err } + if _, ok := d.GetOk("database_import"); ok { + if !strings.EqualFold(createMode, "default") { + return fmt.Errorf("database_import can only be used when create_mode is Default") + } + importParameters := expandAzureRmSqlDatabaseImport(d) + importFuture, err := client.CreateImportOperation(ctx, resourceGroup, serverName, name, "terraform", importParameters) + if err != nil { + return err + } + + // this is set in config.go, but something sets + // it back to 15 minutes, which isn't long enough + // for most imports + client.Client.PollingDuration = 60 * time.Minute + + err = importFuture.WaitForCompletion(ctx, client.Client) + if err != nil { + return err + } + } + resp, err := client.Get(ctx, resourceGroup, serverName, name, "") if err != nil { return err @@ -399,3 +421,21 @@ func flattenEncryptionStatus(encryption *[]sql.TransparentDataEncryption) string return "" } + +func expandAzureRmSqlDatabaseImport(d *schema.ResourceData) sql.ImportExtensionRequest { + v := d.Get("database_import") + dbimportRefs := v.([]interface{}) + dbimportRef := dbimportRefs[0].(map[string]interface{}) + return sql.ImportExtensionRequest{ + Name: utils.String("terraform"), + ImportExtensionProperties: &sql.ImportExtensionProperties{ + 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: sql.AuthenticationType(dbimportRef["authentication_type"].(string)), + OperationMode: utils.String(dbimportRef["operation_mode"].(string)), + }, + } +} diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index 38c6e2868cbf..eedbd1151740 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -52,6 +52,8 @@ The following arguments are supported: * `create_mode` - (Optional) Specifies the type of database to create. Defaults to `Default`. See below for the accepted values/ +* `database_import` - (Optional) A Database Import block as documented below. `create_mode` must be set to `Default`. + * `source_database_id` - (Optional) The URI of the source database if `create_mode` value is not `Default`. * `restore_point_in_time` - (Optional) The point in time for the restore. Only applies if `create_mode` is `PointInTimeRestore` e.g. 2013-11-08T22:00:40Z @@ -73,6 +75,16 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. +`database_import` 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`. +* `operation_mode` - (Required) Specifies the type of import operation being performed. The only allowable value is `Import`. + ## Attributes Reference The following attributes are exported: From 1ba3169e735feacedeb2eb310053866f4bf95ab4 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Tue, 10 Apr 2018 16:42:27 +0100 Subject: [PATCH 3/6] PR tweaks --- azurerm/resource_arm_sql_database.go | 15 +++++++++------ website/docs/r/sql_database.html.markdown | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 60377fa8a0fa..9d6e1cb26847 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -69,8 +69,9 @@ func resourceArmSqlDatabase() *schema.Resource { Required: true, }, "storage_key": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Sensitive: true, }, "storage_key_type": { Type: schema.TypeString, @@ -84,8 +85,9 @@ func resourceArmSqlDatabase() *schema.Resource { Required: true, }, "administrator_login_password": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + Sensitive: true, }, "authentication_type": { Type: schema.TypeString, @@ -96,7 +98,8 @@ func resourceArmSqlDatabase() *schema.Resource { }, "operation_mode": { Type: schema.TypeString, - Required: true, + Optional: true, + Default: "Import", ValidateFunc: validation.StringInSlice([]string{ "Import", }, true), @@ -291,7 +294,7 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} return fmt.Errorf("database_import can only be used when create_mode is Default") } importParameters := expandAzureRmSqlDatabaseImport(d) - importFuture, err := client.CreateImportOperation(ctx, resourceGroup, serverName, name, "terraform", importParameters) + importFuture, err := client.CreateImportOperation(ctx, resourceGroup, serverName, name, importParameters) if err != nil { return err } diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index c9b760d53a54..932ce8a2ba2b 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -83,7 +83,7 @@ The following arguments are supported: * `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`. -* `operation_mode` - (Required) Specifies the type of import operation being performed. The only allowable value is `Import`. +* `operation_mode` - (Optional) Specifies the type of import operation being performed. The only allowable value is `Import`. ## Attributes Reference From e3b9a4e71e6010388160d253659cadcc884cdf95 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Tue, 10 Apr 2018 16:47:08 +0100 Subject: [PATCH 4/6] rename database_import to import --- azurerm/resource_arm_sql_database.go | 8 ++++---- website/docs/r/sql_database.html.markdown | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index 9d6e1cb26847..b014fccee2b9 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -58,7 +58,7 @@ func resourceArmSqlDatabase() *schema.Resource { DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, - "database_import": { + "import": { Type: schema.TypeList, Optional: true, MaxItems: 1, @@ -289,9 +289,9 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} return err } - if _, ok := d.GetOk("database_import"); ok { + if _, ok := d.GetOk("import"); ok { if !strings.EqualFold(createMode, "default") { - return fmt.Errorf("database_import can only be used when create_mode is Default") + return fmt.Errorf("import can only be used when create_mode is Default") } importParameters := expandAzureRmSqlDatabaseImport(d) importFuture, err := client.CreateImportOperation(ctx, resourceGroup, serverName, name, importParameters) @@ -430,7 +430,7 @@ func flattenEncryptionStatus(encryption *[]sql.TransparentDataEncryption) string } func expandAzureRmSqlDatabaseImport(d *schema.ResourceData) sql.ImportExtensionRequest { - v := d.Get("database_import") + v := d.Get("import") dbimportRefs := v.([]interface{}) dbimportRef := dbimportRefs[0].(map[string]interface{}) return sql.ImportExtensionRequest{ diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index 932ce8a2ba2b..ef257275f993 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -52,7 +52,7 @@ The following arguments are supported: * `create_mode` - (Optional) Specifies the type of database to create. Defaults to `Default`. See below for the accepted values/ -* `database_import` - (Optional) A Database Import block as documented below. `create_mode` must be set to `Default`. +* `import` - (Optional) A Database Import block as documented below. `create_mode` must be set to `Default`. * `source_database_id` - (Optional) The URI of the source database if `create_mode` value is not `Default`. @@ -75,7 +75,7 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. -`database_import` supports the following: +`import` 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. From a4159d06e69d447f2a1cc639396770ec7ee4d490 Mon Sep 17 00:00:00 2001 From: Henry Buckle Date: Sat, 5 May 2018 10:39:00 +0100 Subject: [PATCH 5/6] add acc test --- azurerm/resource_arm_sql_database_test.go | 89 ++++++++++++++++++++++ azurerm/testdata/sql_import.bacpac | Bin 0 -> 3016 bytes 2 files changed, 89 insertions(+) create mode 100644 azurerm/testdata/sql_import.bacpac diff --git a/azurerm/resource_arm_sql_database_test.go b/azurerm/resource_arm_sql_database_test.go index 24eb65fc53dc..7a65cab5cf93 100644 --- a/azurerm/resource_arm_sql_database_test.go +++ b/azurerm/resource_arm_sql_database_test.go @@ -265,6 +265,25 @@ func testCheckAzureRMSqlDatabaseDisappears(name string) resource.TestCheckFunc { } } +func TestAccAzureRMSqlDatabase_bacpac(t *testing.T) { + ri := acctest.RandInt() + config := testAccAzureRMSqlDatabase_bacpac(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists("azurerm_sql_database.test"), + ), + }, + }, + }) +} + func testAccAzureRMSqlDatabase_basic(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -496,3 +515,73 @@ resource "azurerm_sql_database" "test" { } `, rInt, location, rInt, rInt) } + +func testAccAzureRMSqlDatabase_bacpac(rInt int, location string) string { + return fmt.Sprintf(` + resource "azurerm_resource_group" "test" { + name = "acctestRG_%d" + location = "%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" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" + } + + resource "azurerm_storage_blob" "test" { + name = "test.bacpac" + resource_group_name = "${azurerm_resource_group.test.name}" + 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_server" "test" { + name = "acctestsqlserver%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" + } + + resource "azurerm_sql_firewall_rule" "test" { + name = "allowazure" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test.name}" + start_ip_address = "0.0.0.0" + end_ip_address = "0.0.0.0" + } + + resource "azurerm_sql_database" "test" { + name = "acctestdb%d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Standard" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + requested_service_objective_name = "S0" + + import { + storage_uri = "${azurerm_storage_blob.test.url}" + storage_key = "${azurerm_storage_account.test.primary_access_key}" + storage_key_type = "StorageAccessKey" + administrator_login = "${azurerm_sql_server.test.administrator_login}" + administrator_login_password = "${azurerm_sql_server.test.administrator_login_password}" + authentication_type = "SQL" + } + } + `, rInt, location, rInt, rInt, rInt) +} diff --git a/azurerm/testdata/sql_import.bacpac b/azurerm/testdata/sql_import.bacpac new file mode 100644 index 0000000000000000000000000000000000000000..98825ab441bb5bf9ad4e515bd99648a3e1af726d GIT binary patch literal 3016 zcmbtWd0Z1`8XiEAqgEDa5v1-kH4ua(Gs)y6Ny`yj4MOCQu81;81{ul4%mhS5cRjFb ztJP``JP}1HZK1Uu*i|cvwpv$E&{|Ynq`O{VTdmZq?KcTY!Q#(9HpwKvyx)61@AJLi zr`P!m34tKU56ab9Q_dw-c@y3clsgQ9{GkZQVlxqD!EB2e-Z~26ZDAGv{OZoiEo?_Z z%6jsCJN!%8yBk-2{M-(%?w#OsACcyOs@BWfxq%=hPRJn6kp zMnqJnuWQ|4IqcI>_}lgKzK7>_#I?3%Pi<`8yldJ7{`p8d6F-i7K7NJYnwXwV1u|xC zSX;9-cJ06Nhw?f`>;7F6|J~IMFT5_ecz9pN)MGupsN2S9C#Yu>MWzUe(LoMM(JD_A6CG`8Zg7}(9IrJ_3vRjLH-vX0 z`>OWy@Y7SOj`n_a1QV+p&xL+&Uley?jYFzhuH1d*H8iF^bWi@4>0U48Y~QY2EZKc= ztfFU3(Fc<+kKA@bvm|YMaNvHgi^$t?fzv0?o25wm&$*N#r{p2R+7Hrqd+l00t+W2- z+I96`;wSkJ68AL;DmSh;Xv$i8dyb=}gGbg{x4rL+XI?6kcZG+H;WS_FI`@y@wNYn2 zj0n@@96R+*Qx&0_5j*ov%TMjv86{DXz26$B8Ofv7XNcRYVS|o)w&yOlydr;BUGcV^ z$l>sRkYOZS9~TwS~W>sz5aKaG!k|Dj*cPxJn=AzOMi_V|08cS2Vkot?8=CSKln zAgbHk3O(`)jawp={TQ$I@0t={w5II1TvK;rug|Y_$?_fHkM9RwefZ0Qd8bzjBTM!s zq|9%4rFVh1egIGJ{`X<}Ccwla;28mUnuHrC5e#m^8T?snm8|^q`9^ru;*yaa|Excm z78jOyy|c4(Yf;o)n=XBeclgh35%b2*h+kOI-XkdKcz8d!`&4Sz@|VMJhfhUQ{gvHu zSIf(%ryrVnc8Va>P4YdDKy}_#~`oi@)(*-G068%Fqg>ijy*0 zIZCxYa8=g}vGtEOcig_y_P^3=Z7Yto4wcr&#ORM|R7&e}De0l(w#!noVtq3d7 zcKW0D-}Qa(M9?xieQA+>&G+BtF~439Z!F7tsd?CohG^4$sJ1Tii<(f!`dtU`I}xqK zO+L>jVb_&eRc-q^yZ_48762-Npgb^Y>=s|-MPCSFp8!x>8b!_|ts@g0m6X^tI=j6tuxge2b0g2b6(X94^RP8xSYbkz)Gt*1q@?X3Wc<>fUw}S zz(N`+8*R&H1V)=hNEexDf&y-ZCfq2@ASeQ5VOePScGE^=X#UO|h0fre2tJr6ywVE^tf}nioC)23{ zv;;uLzEnb1p-&g|)#NZTES{Q49*SfXnE@vNJp_POv2b5E)F|cxDHcw2m>CB}sI7#9 zp>T67talj9q)|tdX4(n~tJ;8w^CkJRd=xcF5L}D{#QFsq7~9Por+2YbA`*x_>h86H z78y=XYyMw`d!qFDV}q!K1AC});oyeL_0OG^2QWBeatiEPgF&~XFfT)o@)NVLXqcx< zzz`88MkLWNA4b{Tf?=3cfWW-hrC@z{fd52?83s1MPzIxNB_da13Ra$IvzLN7QNX}F zV>J9nutXaLwv>}+KuZgTBxR>ant-(?lHI{d7-$fD15OhrIE6G4RvJtTm?y>f29k+} zZB{s&w3=)s^nje%-2`-jH&`kV!;xkt4rCZPlZk_Q2@cY1f>BJY5G!F&)Zf5Jriw}0 zMn!|!!w!&Qf^x&s*Q_+dEW!wOnZwHT+sAAaHnTK4n<}kARl+AlE_=`mJwaJWnw@-r z-weTST8#*FZ4hx^OyQq`x|4HuP?cCf7z=5K#hs8x0B2F8nj`dF0XZ5(B2E@3DiV_9 zC@Mqb5{X2tKodj?M2m_MnJ5{-4}wl@B!7$?bCRv;(ofgTf(DzvEG_8w!q02pR(3-Qc&$>Ed^%x%o!` literal 0 HcmV?d00001 From 4c7ae1b2d054a4f75886e3060d0d840ab4c6b1e5 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 19 Jun 2018 10:28:53 +0200 Subject: [PATCH 6/6] Handling case-insensitivity --- azurerm/resource_arm_sql_database.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_sql_database.go b/azurerm/resource_arm_sql_database.go index b014fccee2b9..b31573bcffd4 100644 --- a/azurerm/resource_arm_sql_database.go +++ b/azurerm/resource_arm_sql_database.go @@ -77,8 +77,10 @@ func resourceArmSqlDatabase() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - "StorageAccessKey", "SharedAccessKey", + "StorageAccessKey", + "SharedAccessKey", }, true), + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, "administrator_login": { Type: schema.TypeString, @@ -93,8 +95,10 @@ func resourceArmSqlDatabase() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - "SQL", "ADPassword", + "ADPassword", + "SQL", }, true), + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, "operation_mode": { Type: schema.TypeString, @@ -103,6 +107,7 @@ func resourceArmSqlDatabase() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{ "Import", }, true), + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, }, }, },