-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
New Resource: azurerm_sql_virtual_network_rule
#978
Changes from 16 commits
70d742e
d02ef1a
35cb61e
d7d4f88
8e06967
0888af6
46aaeb2
8a15347
906b2f2
d4ae4fd
3c9bbc2
d8fa04b
8b7d306
40a50bc
9517eb1
1aaf309
193e991
712de07
0c267e9
d287702
c9350bc
299731e
b6c69da
efd737a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package azurerm | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
) | ||
|
||
func TestAccAzureRMSqlVirtualNetworkRule_importBasic(t *testing.T) { | ||
resourceName := "azurerm_sql_virtual_network_rule.test" | ||
|
||
ri := acctest.RandInt() | ||
config := testAccAzureRMSqlVirtualNetworkRule_basic(ri, testLocation()) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testCheckAzureRMSqlVirtualNetworkRuleDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: config, | ||
}, | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
package azurerm | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"regexp" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/sql/mgmt/2015-05-01-preview/sql" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func resourceArmSqlVirtualNetworkRule() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceArmSqlVirtualNetworkRuleCreateUpdate, | ||
Read: resourceArmSqlVirtualNetworkRuleRead, | ||
Update: resourceArmSqlVirtualNetworkRuleCreateUpdate, | ||
Delete: resourceArmSqlVirtualNetworkRuleDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validateSqlVirtualNetworkRuleName, | ||
}, | ||
|
||
"resource_group_name": resourceGroupNameSchema(), | ||
|
||
"server_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"subnet_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tombuildsstuff It does indeed look like you can change the subnets of a rule, and it does apply correctly. I will make a task to create a test case for that. 😄 On a side note, I also tested migrating from one SQL server to another without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✅ |
||
}, | ||
|
||
"ignore_missing_vnet_service_endpoint": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, //When not provided, Azure defaults to false | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceArmSqlVirtualNetworkRuleCreateUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).sqlVirtualNetworkRulesClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
name := d.Get("name").(string) | ||
serverName := d.Get("server_name").(string) | ||
resourceGroup := d.Get("resource_group_name").(string) | ||
virtualNetworkSubnetId := d.Get("subnet_id").(string) | ||
ignoreMissingVnetServiceEndpoint := d.Get("ignore_missing_vnet_service_endpoint").(bool) | ||
|
||
parameters := sql.VirtualNetworkRule{ | ||
VirtualNetworkRuleProperties: &sql.VirtualNetworkRuleProperties{ | ||
VirtualNetworkSubnetID: utils.String(virtualNetworkSubnetId), | ||
IgnoreMissingVnetServiceEndpoint: utils.Bool(ignoreMissingVnetServiceEndpoint), | ||
}, | ||
} | ||
|
||
_, err := client.CreateOrUpdate(ctx, resourceGroup, serverName, name, parameters) | ||
if err != nil { | ||
return fmt.Errorf("Error creating SQL Virtual Network Rule: %+v", err) | ||
} | ||
|
||
resp, err := client.Get(ctx, resourceGroup, serverName, name) | ||
if err != nil { | ||
return fmt.Errorf("Error retrieving SQL Virtual Network Rule: %+v", err) | ||
} | ||
|
||
d.SetId(*resp.ID) | ||
|
||
return resourceArmSqlVirtualNetworkRuleRead(d, meta) | ||
} | ||
|
||
func resourceArmSqlVirtualNetworkRuleRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).sqlVirtualNetworkRulesClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resourceGroup := id.ResourceGroup | ||
serverName := id.Path["servers"] | ||
name := id.Path["virtualNetworkRules"] | ||
|
||
resp, err := client.Get(ctx, resourceGroup, serverName, name) | ||
if err != nil { | ||
if utils.ResponseWasNotFound(resp.Response) { | ||
log.Printf("[INFO] Error reading SQL Virtual Network Rule %q - removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Error reading SQL Virtual Network Rule: %+v", err) | ||
} | ||
|
||
d.Set("name", resp.Name) | ||
d.Set("resource_group_name", resourceGroup) | ||
d.Set("server_name", serverName) | ||
|
||
if props := resp.VirtualNetworkRuleProperties; props != nil { | ||
d.Set("subnet_id", props.VirtualNetworkSubnetID) | ||
d.Set("ignore_missing_vnet_service_endpoint", props.IgnoreMissingVnetServiceEndpoint) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceArmSqlVirtualNetworkRuleDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).sqlVirtualNetworkRulesClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
resourceGroup := id.ResourceGroup | ||
serverName := id.Path["servers"] | ||
name := id.Path["virtualNetworkRules"] | ||
|
||
future, err := client.Delete(ctx, resourceGroup, serverName, name) | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checking the SDK - it appears that 404 will return an error here; do we want to check for that? e.g.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tombuildsstuff If the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it'll contain the HTTP response, but not necessarily a valid future (since a 500 for example won't contain the headers needed for a future, at least from my understanding) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
//If the error is that the resource we want to delete does not exist in the first | ||
//place (404), then just return with no error. | ||
if response.WasNotFound(future.Response()) { | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Error deleting SQL Virtual Network Rule: %+v", err) | ||
} | ||
|
||
err = future.WaitForCompletion(ctx, client.Client) | ||
if err != nil { | ||
|
||
//Same deal as before. Just in case. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to clarify this, this is the main code path - as the deletion of the SQL Network Rule's should be a long running operation (LRO); afaik :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tombuildsstuff Could you elaborate a bit on this comment? |
||
if response.WasNotFound(future.Response()) { | ||
return nil | ||
} | ||
|
||
return err | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checking the SDK - it appears that 404 will return an error here; do we want to check for that? e.g.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
|
||
return nil | ||
} | ||
|
||
/* | ||
This function checks the format of the SQL Virtual Network Rule Name to make sure that | ||
it does not contain any potentially invalid values. | ||
*/ | ||
func validateSqlVirtualNetworkRuleName(v interface{}, k string) (ws []string, errors []error) { | ||
value := v.(string) | ||
|
||
// Cannot be more than 128 characters | ||
if len(value) > 128 { | ||
errors = append(errors, fmt.Errorf( | ||
"%q cannot be longer than 128 characters: %q", k, value)) | ||
return | ||
} | ||
|
||
// Cannot be empty | ||
if len(value) == 0 { | ||
errors = append(errors, fmt.Errorf( | ||
"%q cannot be an empty string: %q", k, value)) | ||
return | ||
} | ||
|
||
// Must only contain alphanumeric characters or hyphens | ||
if !regexp.MustCompile(`^[A-Za-z0-9-]+$`).MatchString(value) { | ||
errors = append(errors, fmt.Errorf( | ||
"only alphanumeric characters and hyphens allowed in %q: %q", | ||
k, value)) | ||
return | ||
} | ||
|
||
// Cannot end in a hyphen | ||
if regexp.MustCompile(`-$`).MatchString(value) { | ||
errors = append(errors, fmt.Errorf( | ||
"%q cannot end with a hyphen: %q", k, value)) | ||
return | ||
} | ||
|
||
// Cannot start with a number or hyphen | ||
if regexp.MustCompile(`^[0-9-]`).MatchString(value) { | ||
errors = append(errors, fmt.Errorf( | ||
"%q cannot start with a number or hyphen: %q", k, value)) | ||
return | ||
} | ||
|
||
// There are multiple returns in the case that there is more than one invalid | ||
// case applied to the name. | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor can we switch this over to using the new registration syntax? e.g. `c.configureClient(&sqlVNRClient.Client, auth)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅