terraform/builtin/providers/azure/resource_azure_sql_database...

226 lines
7.1 KiB
Go

package azure
import (
"fmt"
"log"
"strings"
"github.com/Azure/azure-sdk-for-go/management/sql"
"github.com/hashicorp/terraform/helper/schema"
)
// resourceAzureSqlDatabaseServerFirewallRule returns the *schema.Resource
// associated to a firewall rule of a database server in Azure.
func resourceAzureSqlDatabaseServerFirewallRule() *schema.Resource {
return &schema.Resource{
Create: resourceAzureSqlDatabaseServerFirewallRuleCreate,
Read: resourceAzureSqlDatabaseServerFirewallRuleRead,
Update: resourceAzureSqlDatabaseServerFirewallRuleUpdate,
Delete: resourceAzureSqlDatabaseServerFirewallRuleDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"database_server_names": &schema.Schema{
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Set: schema.HashString,
},
"start_ip": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"end_ip": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
}
}
// resourceAzureSqlDatabaseServerFirewallRuleCreate does all the necessary API
// calls to create the SQL Database Server Firewall Rule on Azure.
func resourceAzureSqlDatabaseServerFirewallRuleCreate(d *schema.ResourceData, meta interface{}) error {
sqlClient := meta.(*Client).sqlClient
name := d.Get("name").(string)
params := sql.FirewallRuleCreateParams{
Name: name,
StartIPAddress: d.Get("start_ip").(string),
EndIPAddress: d.Get("end_ip").(string),
}
// loop over all the database servers and apply the firewall rule to each:
serverNames := d.Get("database_server_names").(*schema.Set).List()
for _, srv := range serverNames {
serverName := srv.(string)
log.Printf("[INFO] Sending Azure Database Server Firewall Rule %q creation request for Server %q.", name, serverName)
if err := sqlClient.CreateFirewallRule(serverName, params); err != nil {
return fmt.Errorf("Error creating Azure Database Server Firewall Rule %q for Server %q: %s", name, serverName, err)
}
}
d.SetId(name)
return nil
}
// resourceAzureSqlDatabaseServerFirewallRuleRead does all the necessary API
// calls to read the state of the SQL Database Server Firewall Rule on Azure.
func resourceAzureSqlDatabaseServerFirewallRuleRead(d *schema.ResourceData, meta interface{}) error {
sqlClient := meta.(*Client).sqlClient
name := d.Get("name").(string)
remaining := schema.NewSet(schema.HashString, nil)
// for each of our servers; check to see if the rule is still present:
var found bool
for _, srv := range d.Get("database_server_names").(*schema.Set).List() {
serverName := srv.(string)
log.Printf("[INFO] Sending Azure Database Server Firewall Rule list query for server %q.", serverName)
rules, err := sqlClient.ListFirewallRules(serverName)
if err != nil {
if strings.Contains(err.Error(), "does not exist") {
// it means that the database server this rule belonged to has
// been deleted in the meantime.
continue
} else {
return fmt.Errorf("Error getting Azure Firewall Rules for Database Server %q: %s", serverName, err)
}
}
// look for our rule:
for _, rule := range rules.FirewallRules {
if rule.Name == name {
found = true
remaining.Add(serverName)
break
}
}
}
// check to see if there is still any Database Server still having this rule:
if !found {
d.SetId("")
return nil
}
// else; update the list of Database Servers still having this rule:
d.Set("database_server_names", remaining)
return nil
}
// resourceAzureSqlDatabaseServerFirewallRuleUpdate does all the necessary API
// calls to update the state of the SQL Database Server Firewall Rule on Azure.
func resourceAzureSqlDatabaseServerFirewallRuleUpdate(d *schema.ResourceData, meta interface{}) error {
sqlClient := meta.(*Client).sqlClient
var found bool
name := d.Get("name").(string)
updateParams := sql.FirewallRuleUpdateParams{
Name: name,
StartIPAddress: d.Get("start_ip").(string),
EndIPAddress: d.Get("end_ip").(string),
}
// for each of the Database Servers our rules concerns; issue the update:
remaining := schema.NewSet(schema.HashString, nil)
for _, srv := range d.Get("database_server_names").(*schema.Set).List() {
serverName := srv.(string)
log.Printf("[INFO] Issuing Azure Database Server Firewall Rule list for Database Server %q: %s.", name, serverName)
rules, err := sqlClient.ListFirewallRules(serverName)
if err != nil {
if strings.Contains(err.Error(), "does not exist") {
// it means that the database server this rule belonged to has
// been deleted in the meantime.
continue
} else {
return fmt.Errorf("Error getting Azure Firewall Rules for Database Server %q: %s", serverName, err)
}
}
// look for our rule:
for _, rule := range rules.FirewallRules {
if rule.Name == name {
// take note of the fact that this Database Server still has
// this rule:
found = true
remaining.Add(serverName)
// go ahead and update the rule:
log.Printf("[INFO] Issuing update of Azure Database Server Firewall Rule %q in Server %q.", name, serverName)
if err := sqlClient.UpdateFirewallRule(serverName, name, updateParams); err != nil {
return fmt.Errorf("Error updating Azure Database Server Firewall Rule %q for Server %q: %s", name, serverName, err)
}
break
}
}
}
// check to see if the rule is still exists on any of the servers:
if !found {
d.SetId("")
return nil
}
// else; update the list with the remaining Servers:
d.Set("database_server_names", remaining)
return nil
}
// resourceAzureSqlDatabaseServerFirewallRuleDelete does all the necessary API
// calls to delete the SQL Database Server Firewall Rule on Azure.
func resourceAzureSqlDatabaseServerFirewallRuleDelete(d *schema.ResourceData, meta interface{}) error {
sqlClient := meta.(*Client).sqlClient
name := d.Get("name").(string)
for _, srv := range d.Get("database_server_names").(*schema.Set).List() {
serverName := srv.(string)
log.Printf("[INFO] Sending Azure Database Server Firewall Rule list query for Server %q.", serverName)
rules, err := sqlClient.ListFirewallRules(serverName)
if err != nil {
if strings.Contains(err.Error(), "does not exist") {
// it means that the database server this rule belonged to has
// been deleted in the meantime.
continue
} else {
return fmt.Errorf("Error getting Azure Firewall Rules for Database Server %q: %s", serverName, err)
}
}
// look for our rule:
for _, rule := range rules.FirewallRules {
if rule.Name == name {
// go ahead and delete the rule:
log.Printf("[INFO] Issuing deletion of Azure Database Server Firewall Rule %q in Server %q.", name, serverName)
if err := sqlClient.DeleteFirewallRule(serverName, name); err != nil {
if strings.Contains(err.Error(), "Cannot open server") {
break
}
return fmt.Errorf("Error deleting Azure Database Server Firewall Rule %q for Server %q: %s", name, serverName, err)
}
break
}
}
}
return nil
}