Merge pull request #5003 from stack72/azurerm-sql-database

provider/azurerm: Add azurerm_sql_database resource
This commit is contained in:
James Nugent 2016-02-04 19:16:39 -05:00
commit d5601a41d1
27 changed files with 661 additions and 100 deletions

6
Godeps/Godeps.json generated
View File

@ -526,15 +526,15 @@
}, },
{ {
"ImportPath": "github.com/jen20/riviera/azure", "ImportPath": "github.com/jen20/riviera/azure",
"Rev": "478cbee6e83468ab998195f485cf8f62069a8024" "Rev": "b5328db47f3ec02cbf39c2c31ac4072bda2ff05b"
}, },
{ {
"ImportPath": "github.com/jen20/riviera/dns", "ImportPath": "github.com/jen20/riviera/dns",
"Rev": "478cbee6e83468ab998195f485cf8f62069a8024" "Rev": "b5328db47f3ec02cbf39c2c31ac4072bda2ff05b"
}, },
{ {
"ImportPath": "github.com/jen20/riviera/sql", "ImportPath": "github.com/jen20/riviera/sql",
"Rev": "478cbee6e83468ab998195f485cf8f62069a8024" "Rev": "b5328db47f3ec02cbf39c2c31ac4072bda2ff05b"
}, },
{ {
"ImportPath": "github.com/jmespath/go-jmespath", "ImportPath": "github.com/jmespath/go-jmespath",

View File

@ -62,6 +62,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_storage_queue": resourceArmStorageQueue(), "azurerm_storage_queue": resourceArmStorageQueue(),
"azurerm_dns_zone": resourceArmDnsZone(), "azurerm_dns_zone": resourceArmDnsZone(),
"azurerm_sql_server": resourceArmSqlServer(), "azurerm_sql_server": resourceArmSqlServer(),
"azurerm_sql_database": resourceArmSqlDatabase(),
}, },
ConfigureFunc: providerConfigure, ConfigureFunc: providerConfigure,
} }

View File

@ -0,0 +1,257 @@
package azurerm
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
"github.com/jen20/riviera/azure"
"github.com/jen20/riviera/sql"
)
func resourceArmSqlDatabase() *schema.Resource {
return &schema.Resource{
Create: resourceArmSqlDatabaseCreate,
Read: resourceArmSqlDatabaseRead,
Update: resourceArmSqlDatabaseCreate,
Delete: resourceArmSqlDatabaseDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"location": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: azureRMNormalizeLocation,
},
"resource_group_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"server_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"create_mode": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "Default",
},
"source_database_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"restore_point_in_time": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"edition": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateArmSqlDatabaseEdition,
},
"collation": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"max_size_bytes": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"requested_service_objective_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"requested_service_objective_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"source_database_deletion_date": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"elastic_pool_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"encryption": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"creation_date": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"default_secondary_location": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
}
}
func resourceArmSqlDatabaseCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
rivieraClient := client.rivieraClient
tags := d.Get("tags").(map[string]interface{})
expandedTags := expandTags(tags)
command := &sql.CreateOrUpdateDatabase{
Name: d.Get("name").(string),
Location: d.Get("location").(string),
ResourceGroupName: d.Get("resource_group_name").(string),
ServerName: d.Get("server_name").(string),
Tags: *expandedTags,
CreateMode: azure.String(d.Get("create_mode").(string)),
}
if v, ok := d.GetOk("source_database_id"); ok {
command.SourceDatabaseID = azure.String(v.(string))
}
if v, ok := d.GetOk("edition"); ok {
command.Edition = azure.String(v.(string))
}
if v, ok := d.GetOk("collation"); ok {
command.Collation = azure.String(v.(string))
}
if v, ok := d.GetOk("max_size_bytes"); ok {
command.MaxSizeBytes = azure.String(v.(string))
}
if v, ok := d.GetOk("source_database_deletion_date"); ok {
command.SourceDatabaseDeletionDate = azure.String(v.(string))
}
if v, ok := d.GetOk("requested_service_objective_id"); ok {
command.RequestedServiceObjectiveID = azure.String(v.(string))
}
if v, ok := d.GetOk("requested_service_objective_name"); ok {
command.RequestedServiceObjectiveName = azure.String(v.(string))
}
createRequest := rivieraClient.NewRequest()
createRequest.Command = command
createResponse, err := createRequest.Execute()
if err != nil {
return fmt.Errorf("Error creating SQL Database: %s", err)
}
if !createResponse.IsSuccessful() {
return fmt.Errorf("Error creating SQL Database: %s", createResponse.Error)
}
readRequest := rivieraClient.NewRequest()
readRequest.Command = &sql.GetDatabase{
Name: d.Get("name").(string),
ResourceGroupName: d.Get("resource_group_name").(string),
ServerName: d.Get("server_name").(string),
}
readResponse, err := readRequest.Execute()
if err != nil {
return fmt.Errorf("Error reading SQL Database: %s", err)
}
if !readResponse.IsSuccessful() {
return fmt.Errorf("Error reading SQL Database: %s", readResponse.Error)
}
resp := readResponse.Parsed.(*sql.GetDatabaseResponse)
d.SetId(*resp.ID)
return resourceArmSqlDatabaseRead(d, meta)
}
func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
rivieraClient := client.rivieraClient
readRequest := rivieraClient.NewRequestForURI(d.Id())
readRequest.Command = &sql.GetDatabase{}
readResponse, err := readRequest.Execute()
if err != nil {
return fmt.Errorf("Error reading SQL Database: %s", err)
}
if !readResponse.IsSuccessful() {
log.Printf("[INFO] Error reading SQL Database %q - removing from state", d.Id())
d.SetId("")
return fmt.Errorf("Error reading SQL Database: %s", readResponse.Error)
}
resp := readResponse.Parsed.(*sql.GetDatabaseResponse)
d.Set("name", resp.Name)
d.Set("creation_date", resp.CreationDate)
d.Set("default_secondary_location", resp.DefaultSecondaryLocation)
return nil
}
func resourceArmSqlDatabaseDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
rivieraClient := client.rivieraClient
deleteRequest := rivieraClient.NewRequestForURI(d.Id())
deleteRequest.Command = &sql.DeleteDatabase{}
deleteResponse, err := deleteRequest.Execute()
if err != nil {
return fmt.Errorf("Error deleting SQL Database: %s", err)
}
if !deleteResponse.IsSuccessful() {
return fmt.Errorf("Error deleting SQL Database: %s", deleteResponse.Error)
}
return nil
}
func validateArmSqlDatabaseEdition(v interface{}, k string) (ws []string, errors []error) {
editions := map[string]bool{
"Basic": true,
"Standard": true,
"Premium": true,
}
if !editions[v.(string)] {
errors = append(errors, fmt.Errorf("SQL Database Edition can only be Basic, Standard or Premium"))
}
return
}

View File

@ -0,0 +1,229 @@
package azurerm
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/jen20/riviera/sql"
)
func TestResourceAzureRMSqlDatabaseEdition_validation(t *testing.T) {
cases := []struct {
Value string
ErrCount int
}{
{
Value: "Random",
ErrCount: 1,
},
{
Value: "Basic",
ErrCount: 0,
},
{
Value: "Standard",
ErrCount: 0,
},
{
Value: "Premium",
ErrCount: 0,
},
}
for _, tc := range cases {
_, errors := validateArmSqlDatabaseEdition(tc.Value, "azurerm_sql_database")
if len(errors) != tc.ErrCount {
t.Fatalf("Expected the Azure RM SQL Database edition to trigger a validation error")
}
}
}
func TestAccAzureRMSqlDatabase_basic(t *testing.T) {
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAzureRMSqlDatabase_basic, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMSqlDatabaseDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlDatabaseExists("azurerm_sql_database.test"),
),
},
},
})
}
func TestAccAzureRMSqlDatabase_withTags(t *testing.T) {
ri := acctest.RandInt()
preConfig := fmt.Sprintf(testAccAzureRMSqlDatabase_withTags, ri, ri, ri)
postConfig := fmt.Sprintf(testAccAzureRMSqlDatabase_withTagsUpdate, ri, ri, ri)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMSqlDatabaseDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlDatabaseExists("azurerm_sql_database.test"),
resource.TestCheckResourceAttr(
"azurerm_sql_database.test", "tags.#", "2"),
),
},
resource.TestStep{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMSqlDatabaseExists("azurerm_sql_database.test"),
resource.TestCheckResourceAttr(
"azurerm_sql_database.test", "tags.#", "1"),
),
},
},
})
}
func testCheckAzureRMSqlDatabaseExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
conn := testAccProvider.Meta().(*ArmClient).rivieraClient
readRequest := conn.NewRequestForURI(rs.Primary.ID)
readRequest.Command = &sql.GetDatabase{}
readResponse, err := readRequest.Execute()
if err != nil {
return fmt.Errorf("Bad: GetDatabase: %s", err)
}
if !readResponse.IsSuccessful() {
return fmt.Errorf("Bad: GetDatabase: %s", readResponse.Error)
}
return nil
}
}
func testCheckAzureRMSqlDatabaseDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*ArmClient).rivieraClient
for _, rs := range s.RootModule().Resources {
if rs.Type != "azurerm_sql_database" {
continue
}
readRequest := conn.NewRequestForURI(rs.Primary.ID)
readRequest.Command = &sql.GetDatabase{}
readResponse, err := readRequest.Execute()
if err != nil {
return fmt.Errorf("Bad: GetDatabase: %s", err)
}
if readResponse.IsSuccessful() {
return fmt.Errorf("Bad: SQL Database still exists: %s", readResponse.Error)
}
}
return nil
}
var testAccAzureRMSqlDatabase_basic = `
resource "azurerm_resource_group" "test" {
name = "acctest_rg_%d"
location = "West US"
}
resource "azurerm_sql_server" "test" {
name = "acctestsqlserver%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "West US"
version = "12.0"
administrator_login = "mradministrator"
administrator_login_password = "thisIsDog11"
}
resource "azurerm_sql_database" "test" {
name = "acctestdb%d"
resource_group_name = "${azurerm_resource_group.test.name}"
server_name = "${azurerm_sql_server.test.name}"
location = "West US"
edition = "Standard"
collation = "SQL_Latin1_General_CP1_CI_AS"
max_size_bytes = "1073741824"
requested_service_objective_name = "S0"
}
`
var testAccAzureRMSqlDatabase_withTags = `
resource "azurerm_resource_group" "test" {
name = "acctest_rg_%d"
location = "West US"
}
resource "azurerm_sql_server" "test" {
name = "acctestsqlserver%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "West US"
version = "12.0"
administrator_login = "mradministrator"
administrator_login_password = "thisIsDog11"
}
resource "azurerm_sql_database" "test" {
name = "acctestdb%d"
resource_group_name = "${azurerm_resource_group.test.name}"
server_name = "${azurerm_sql_server.test.name}"
location = "West US"
edition = "Standard"
collation = "SQL_Latin1_General_CP1_CI_AS"
max_size_bytes = "1073741824"
requested_service_objective_name = "S0"
tags {
environment = "staging"
database = "test"
}
}
`
var testAccAzureRMSqlDatabase_withTagsUpdate = `
resource "azurerm_resource_group" "test" {
name = "acctest_rg_%d"
location = "West US"
}
resource "azurerm_sql_server" "test" {
name = "acctestsqlserver%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "West US"
version = "12.0"
administrator_login = "mradministrator"
administrator_login_password = "thisIsDog11"
}
resource "azurerm_sql_database" "test" {
name = "acctestdb%d"
resource_group_name = "${azurerm_resource_group.test.name}"
server_name = "${azurerm_sql_server.test.name}"
location = "West US"
edition = "Standard"
collation = "SQL_Latin1_General_CP1_CI_AS"
max_size_bytes = "1073741824"
requested_service_objective_name = "S0"
tags {
environment = "production"
}
}
`

View File

@ -1,26 +1,25 @@
package azure package azure
// ApiCall must be implemented by structures which represent requests to the // APICall must be implemented by structures which represent requests to the
// ARM API in order that the generic request handling layer has sufficient // ARM API in order that the generic request handling layer has sufficient
// information to execute requests. // information to execute requests.
type ApiCall interface { type APICall interface {
ApiInfo() ApiInfo APIInfo() APIInfo
} }
// ApiInfo contains information about a request to the ARM API - which API // APIInfo contains information about a request to the ARM API - which API
// version is required, the HTTP method to use, and a factory function for // version is required, the HTTP method to use, and a factory function for
// responses. // responses.
type ApiInfo struct { type APIInfo struct {
ApiVersion string APIVersion string
Method string Method string
SkipArmBoilerplate bool URLPathFunc func() string
URLPathFunc func() string ResponseTypeFunc func() interface{}
ResponseTypeFunc func() interface{}
} }
// HasBody returns true if the API Request should have a body. This is usually // HasBody returns true if the API Request should have a body. This is usually
// the case for PUT, PATCH or POST operations, but is not the case for GET operations. // the case for PUT, PATCH or POST operations, but is not the case for GET operations.
// TODO(jen20): This may need revisiting at some point. // TODO(jen20): This may need revisiting at some point.
func (apiInfo ApiInfo) HasBody() bool { func (apiInfo APIInfo) HasBody() bool {
return apiInfo.Method == "POST" || apiInfo.Method == "PUT" || apiInfo.Method == "PATCH" return apiInfo.Method == "POST" || apiInfo.Method == "PUT" || apiInfo.Method == "PATCH"
} }

View File

@ -10,7 +10,7 @@ import (
type Client struct { type Client struct {
logger *log.Logger logger *log.Logger
BaseUrl string BaseURL string
subscriptionID string subscriptionID string
tokenRequester *tokenRequester tokenRequester *tokenRequester
@ -26,7 +26,7 @@ func NewClient(creds *AzureResourceManagerCredentials) (*Client, error) {
tr := newTokenRequester(httpClient, creds.ClientID, creds.ClientSecret, creds.TenantID) tr := newTokenRequester(httpClient, creds.ClientID, creds.ClientSecret, creds.TenantID)
return &Client{ return &Client{
BaseUrl: "https://management.azure.com", BaseURL: "https://management.azure.com",
subscriptionID: creds.SubscriptionID, subscriptionID: creds.SubscriptionID,
httpClient: httpClient, httpClient: httpClient,
tokenRequester: tr, tokenRequester: tr,

View File

@ -13,9 +13,9 @@ type CreateResourceGroup struct {
Tags map[string]*string `json:"-" riviera:"tags"` Tags map[string]*string `json:"-" riviera:"tags"`
} }
func (command CreateResourceGroup) ApiInfo() ApiInfo { func (command CreateResourceGroup) APIInfo() APIInfo {
return ApiInfo{ return APIInfo{
ApiVersion: resourceGroupAPIVersion, APIVersion: resourceGroupAPIVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: resourceGroupDefaultURLFunc(command.Name), URLPathFunc: resourceGroupDefaultURLFunc(command.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -4,9 +4,9 @@ type DeleteResourceGroup struct {
Name string `json:"-"` Name string `json:"-"`
} }
func (s DeleteResourceGroup) ApiInfo() ApiInfo { func (s DeleteResourceGroup) APIInfo() APIInfo {
return ApiInfo{ return APIInfo{
ApiVersion: resourceGroupAPIVersion, APIVersion: resourceGroupAPIVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: resourceGroupDefaultURLFunc(s.Name), URLPathFunc: resourceGroupDefaultURLFunc(s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -14,9 +14,9 @@ type RegisterResourceProvider struct {
Namespace string `json:"-"` Namespace string `json:"-"`
} }
func (command RegisterResourceProvider) ApiInfo() ApiInfo { func (command RegisterResourceProvider) APIInfo() APIInfo {
return ApiInfo{ return APIInfo{
ApiVersion: resourceGroupAPIVersion, APIVersion: resourceGroupAPIVersion,
Method: "POST", Method: "POST",
URLPathFunc: func() string { URLPathFunc: func() string {
return fmt.Sprintf("providers/%s/register", command.Namespace) return fmt.Sprintf("providers/%s/register", command.Namespace)

View File

@ -16,11 +16,11 @@ import (
) )
type Request struct { type Request struct {
URI *string `json:"-"` URI *string
location *string `json:"location,omitempty"` location *string
tags *map[string]*string `json:"tags,omitempty"` tags *map[string]*string
etag *string `json:"etag,omitempty"` etag *string
Command ApiCall `json:"properties,omitempty"` Command APICall
client *Client client *Client
} }
@ -106,20 +106,20 @@ func (request *Request) pollForAsynchronousResponse(acceptedResponse *http.Respo
} }
} }
func (r *Request) Execute() (*Response, error) { func (request *Request) Execute() (*Response, error) {
apiInfo := r.Command.ApiInfo() apiInfo := request.Command.APIInfo()
var urlString string var urlString string
// Base URL should already be validated by now so Parse is safe without error handling // Base URL should already be validated by now so Parse is safe without error handling
urlObj, _ := url.Parse(r.client.BaseUrl) urlObj, _ := url.Parse(request.client.BaseURL)
// Determine whether to use the URLPathFunc or the URI explictly set in the request // Determine whether to use the URLPathFunc or the URI explicitly set in the request
if r.URI == nil { if request.URI == nil {
urlObj.Path = fmt.Sprintf("/subscriptions/%s/%s", r.client.subscriptionID, strings.TrimPrefix(apiInfo.URLPathFunc(), "/")) urlObj.Path = fmt.Sprintf("/subscriptions/%s/%s", request.client.subscriptionID, strings.TrimPrefix(apiInfo.URLPathFunc(), "/"))
urlString = urlObj.String() urlString = urlObj.String()
} else { } else {
urlObj.Path = *r.URI urlObj.Path = *request.URI
urlString = urlObj.String() urlString = urlObj.String()
} }
@ -131,13 +131,13 @@ func (r *Request) Execute() (*Response, error) {
Tags *map[string]*string `json:"tags,omitempty"` Tags *map[string]*string `json:"tags,omitempty"`
Properties interface{} `json:"properties"` Properties interface{} `json:"properties"`
}{ }{
Properties: r.Command, Properties: request.Command,
} }
if location, hasLocation := readLocation(r.Command); hasLocation { if location, hasLocation := readLocation(request.Command); hasLocation {
bodyStruct.Location = &location bodyStruct.Location = &location
} }
if tags, hasTags := readTags(r.Command); hasTags { if tags, hasTags := readTags(request.Command); hasTags {
if len(tags) > 0 { if len(tags) > 0 {
bodyStruct.Tags = &tags bodyStruct.Tags = &tags
} }
@ -157,25 +157,25 @@ func (r *Request) Execute() (*Response, error) {
} }
query := req.URL.Query() query := req.URL.Query()
query.Set("api-version", apiInfo.ApiVersion) query.Set("api-version", apiInfo.APIVersion)
req.URL.RawQuery = query.Encode() req.URL.RawQuery = query.Encode()
if apiInfo.HasBody() { if apiInfo.HasBody() {
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
} }
err = r.client.tokenRequester.addAuthorizationToRequest(req) err = request.client.tokenRequester.addAuthorizationToRequest(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
httpResponse, err := r.client.httpClient.Do(req) httpResponse, err := request.client.httpClient.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// This is safe to use for every request: we check for it being http.StatusAccepted // This is safe to use for every request: we check for it being http.StatusAccepted
httpResponse, err = r.pollForAsynchronousResponse(httpResponse) httpResponse, err = request.pollForAsynchronousResponse(httpResponse)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -9,12 +9,11 @@ type CreateDNSZone struct {
Tags map[string]*string `json:"-" riviera:"tags"` Tags map[string]*string `json:"-" riviera:"tags"`
} }
func (command CreateDNSZone) ApiInfo() azure.ApiInfo { func (command CreateDNSZone) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: dnsZoneDefaultURLPathFunc(command.ResourceGroupName, command.Name), URLPathFunc: dnsZoneDefaultURLPathFunc(command.ResourceGroupName, command.Name),
SkipArmBoilerplate: true,
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {
return nil return nil
}, },

View File

@ -7,12 +7,11 @@ type DeleteDNSZone struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (command DeleteDNSZone) ApiInfo() azure.ApiInfo { func (command DeleteDNSZone) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: dnsZoneDefaultURLPathFunc(command.ResourceGroupName, command.Name), URLPathFunc: dnsZoneDefaultURLPathFunc(command.ResourceGroupName, command.Name),
SkipArmBoilerplate: true,
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {
return nil return nil
}, },

View File

@ -16,9 +16,9 @@ type GetDNSZone struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s GetDNSZone) ApiInfo() azure.ApiInfo { func (s GetDNSZone) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "GET", Method: "GET",
URLPathFunc: dnsZoneDefaultURLPathFunc(s.ResourceGroupName, s.Name), URLPathFunc: dnsZoneDefaultURLPathFunc(s.ResourceGroupName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -15,9 +15,9 @@ type CreateElasticDatabasePool struct {
DatabaseDTUMax *string `json:"databaseDtuMax,omitempty"` DatabaseDTUMax *string `json:"databaseDtuMax,omitempty"`
} }
func (s CreateElasticDatabasePool) ApiInfo() azure.ApiInfo { func (s CreateElasticDatabasePool) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: sqlElasticPoolDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlElasticPoolDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -29,7 +29,7 @@ type CreateOrUpdateDatabase struct {
Collation *string `json:"collation,omitempty"` Collation *string `json:"collation,omitempty"`
MaxSizeBytes *string `json:"maxSizeBytes,omitempty"` MaxSizeBytes *string `json:"maxSizeBytes,omitempty"`
RequestedServiceObjectiveName *string `json:"requestedServiceObjectiveName,omitempty"` RequestedServiceObjectiveName *string `json:"requestedServiceObjectiveName,omitempty"`
RequestedServiceObjectiveId *string `json:"requestedServiceObjectiveId,omitempty"` RequestedServiceObjectiveID *string `json:"requestedServiceObjectiveId,omitempty"`
CreateMode *string `json:"createMode,omitempty"` CreateMode *string `json:"createMode,omitempty"`
SourceDatabaseID *string `json:"sourceDatabaseId,omitempty"` SourceDatabaseID *string `json:"sourceDatabaseId,omitempty"`
SourceDatabaseDeletionDate *string `json:"sourceDatabaseDeletionDate,omitempty"` SourceDatabaseDeletionDate *string `json:"sourceDatabaseDeletionDate,omitempty"`
@ -37,9 +37,9 @@ type CreateOrUpdateDatabase struct {
ElasticPoolName *string `json:"elasticPoolName,omitempty"` ElasticPoolName *string `json:"elasticPoolName,omitempty"`
} }
func (s CreateOrUpdateDatabase) ApiInfo() azure.ApiInfo { func (s CreateOrUpdateDatabase) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -6,21 +6,21 @@ type CreateOrUpdateFirewallRuleResponse struct {
ID *string `mapstructure:"id"` ID *string `mapstructure:"id"`
Name *string `mapstructure:"name"` Name *string `mapstructure:"name"`
Location *string `mapstructure:"location"` Location *string `mapstructure:"location"`
StartIpAddress *string `json:"startIpAddress,omitempty"` StartIPAddress *string `json:"startIpAddress,omitempty"`
EndIpAddress *string `json:"endIpAddress,omitempty"` EndIPAddress *string `json:"endIpAddress,omitempty"`
} }
type CreateOrUpdateFirewallRule struct { type CreateOrUpdateFirewallRule struct {
Name string `json:"-"` Name string `json:"-"`
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
ServerName string `json:"-"` ServerName string `json:"-"`
StartIpAddress *string `json:"startIpAddress,omitempty"` StartIPAddress *string `json:"startIpAddress,omitempty"`
EndIpAddress *string `json:"endIpAddress,omitempty"` EndIPAddress *string `json:"endIpAddress,omitempty"`
} }
func (s CreateOrUpdateFirewallRule) ApiInfo() azure.ApiInfo { func (s CreateOrUpdateFirewallRule) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -27,9 +27,9 @@ type CreateOrUpdateServer struct {
Version *string `json:"version,omitempty"` Version *string `json:"version,omitempty"`
} }
func (s CreateOrUpdateServer) ApiInfo() azure.ApiInfo { func (s CreateOrUpdateServer) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "PUT", Method: "PUT",
URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name), URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -8,9 +8,9 @@ type DeleteDatabase struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s DeleteDatabase) ApiInfo() azure.ApiInfo { func (s DeleteDatabase) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -8,9 +8,9 @@ type DeleteElasticDatabasePool struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s DeleteElasticDatabasePool) ApiInfo() azure.ApiInfo { func (s DeleteElasticDatabasePool) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: sqlElasticPoolDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlElasticPoolDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -8,9 +8,9 @@ type DeleteFirewallRule struct {
ServerName string `json:"-"` ServerName string `json:"-"`
} }
func (s DeleteFirewallRule) ApiInfo() azure.ApiInfo { func (s DeleteFirewallRule) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -7,9 +7,9 @@ type DeleteServer struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s DeleteServer) ApiInfo() azure.ApiInfo { func (s DeleteServer) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "DELETE", Method: "DELETE",
URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name), URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -25,9 +25,9 @@ type GetDatabase struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s GetDatabase) ApiInfo() azure.ApiInfo { func (s GetDatabase) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "GET", Method: "GET",
URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlDatabaseDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -6,8 +6,8 @@ type GetFirewallRuleResponse struct {
ID *string `mapstructure:"id"` ID *string `mapstructure:"id"`
Name *string `mapstructure:"name"` Name *string `mapstructure:"name"`
Location *string `mapstructure:"location"` Location *string `mapstructure:"location"`
StartIpAddress *string `json:"startIpAddress,omitempty"` StartIPAddress *string `json:"startIpAddress,omitempty"`
EndIpAddress *string `json:"endIpAddress,omitempty"` EndIPAddress *string `json:"endIpAddress,omitempty"`
} }
type GetFirewallRule struct { type GetFirewallRule struct {
@ -16,9 +16,9 @@ type GetFirewallRule struct {
ServerName string `json:"-"` ServerName string `json:"-"`
} }
func (s GetFirewallRule) ApiInfo() azure.ApiInfo { func (s GetFirewallRule) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "GET", Method: "GET",
URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name), URLPathFunc: sqlServerFirewallDefaultURLPath(s.ResourceGroupName, s.ServerName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -22,9 +22,9 @@ type GetServer struct {
ResourceGroupName string `json:"-"` ResourceGroupName string `json:"-"`
} }
func (s GetServer) ApiInfo() azure.ApiInfo { func (s GetServer) APIInfo() azure.APIInfo {
return azure.ApiInfo{ return azure.APIInfo{
ApiVersion: apiVersion, APIVersion: apiVersion,
Method: "GET", Method: "GET",
URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name), URLPathFunc: sqlServerDefaultURLPath(s.ResourceGroupName, s.Name),
ResponseTypeFunc: func() interface{} { ResponseTypeFunc: func() interface{} {

View File

@ -0,0 +1,73 @@
---
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_sql_database"
sidebar_current: "docs-azurerm-resource-sql-database"
description: |-
Create a SQL Database.
---
# azurerm\_sql\_database
Allows you to manage an Azure SQL Database
## Example Usage
```
resource "azurerm_resource_group" "test" {
name = "acceptanceTestResourceGroup1"
location = "West US"
}
resource "azurerm_sql_database" "test" {
name = "MySQLDatabase"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "West US"
tags {
environment = "production"
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the SQL Server.
* `resource_group_name` - (Required) The name of the resource group in which to
create the sql server.
* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.
* `server_name` - (Required) The name of the SQL Server on which to create the database.
* `create_mode` - (Optional) Specifies the type of database to create. Defaults to `Default`. See below for the accepted values/
* `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
* `edition` - (Optional) The edition of the database to be created. Applies only if `create_mode` is `Default`. Valid values are: `Basic`, `Standard`, `Premium`.
* `collation` - (Optional) The name of the collation. Applies only if `create_mode` is `Default`.
* `max_size_bytes` - (Optional) The maximum size that the database can grow to. Applies only if `create_mode` is `Default`.
* `requested_service_object_id` - (Optional) Use `requested_service_object_id` or `requested_service_object_name` to set the performance level for the database.
Valid values are: `S0`, `S1`, `S2`, `S3`, `P1`, `P2`, `P4`, `P6`, `P11` and `ElasticPool`.
* `requested_service_object_name` - (Optional) Use `requested_service_object_name` or `requested_service_object_id` to set the performance level for the database.
* `source_database_deletion_date` - (Optional) The deletion date time of the source database. Only applies to deleted databases where `create_mode` is `PointInTimeRestore`.
* `elastic_pool_name` - (Optional) The name of the elastic database pool.
* `tags` - (Optional) A mapping of tags to assign to the resource.
## Attributes Reference
The following attributes are exported:
* `id` - The SQL Database ID.
* `creation_data` - The creation date of the SQL Database.
* `default_secondary_location` - The default secondary location of the SQL Database.

View File

@ -53,5 +53,5 @@ The following arguments are supported:
The following attributes are exported: The following attributes are exported:
* `id` - The DNS Zone ID. * `id` - The SQL Server ID.
* `fully_qualified_domain_name` - The fully qualified domain name of the Azure SQL Server (e.g. myServerName.database.windows.net) * `fully_qualified_domain_name` - The fully qualified domain name of the Azure SQL Server (e.g. myServerName.database.windows.net)

View File

@ -88,6 +88,10 @@
<a href="#">SQL Resources</a> <a href="#">SQL Resources</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible">
<li<%= sidebar_current("docs-azurerm-resource-sql-database") %>>
<a href="/docs/providers/azurerm/r/sql_database.html">azurerm_sql_database</a>
</li>
<li<%= sidebar_current("docs-azurerm-resource-sql-server") %>> <li<%= sidebar_current("docs-azurerm-resource-sql-server") %>>
<a href="/docs/providers/azurerm/r/sql_server.html">azurerm_sql_server</a> <a href="/docs/providers/azurerm/r/sql_server.html">azurerm_sql_server</a>
</li> </li>