Skip to content

Commit f3cba73

Browse files
authored
azurerm_mysql_flexible_server_firewall_rule: New resource (hashicorp#14136)
Fixes hashicorp#14132
1 parent b930347 commit f3cba73

10 files changed

+702
-0
lines changed

internal/services/mysql/client/client.go

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Client struct {
1212
FirewallRulesClient *mysql.FirewallRulesClient
1313
FlexibleServerConfigurationsClient *mysqlflexibleservers.ConfigurationsClient
1414
FlexibleServerClient *mysqlflexibleservers.ServersClient
15+
FlexibleServerFirewallRulesClient *mysqlflexibleservers.FirewallRulesClient
1516
ServersClient *mysql.ServersClient
1617
ServerKeysClient *mysql.ServerKeysClient
1718
ServerSecurityAlertPoliciesClient *mysql.ServerSecurityAlertPoliciesClient
@@ -32,6 +33,9 @@ func NewClient(o *common.ClientOptions) *Client {
3233
flexibleServerClient := mysqlflexibleservers.NewServersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
3334
o.ConfigureClient(&flexibleServerClient.Client, o.ResourceManagerAuthorizer)
3435

36+
flexibleServerFirewallRulesClient := mysqlflexibleservers.NewFirewallRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
37+
o.ConfigureClient(&flexibleServerFirewallRulesClient.Client, o.ResourceManagerAuthorizer)
38+
3539
flexibleServerConfigurationsClient := mysqlflexibleservers.NewConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
3640
o.ConfigureClient(&flexibleServerConfigurationsClient.Client, o.ResourceManagerAuthorizer)
3741

@@ -55,6 +59,7 @@ func NewClient(o *common.ClientOptions) *Client {
5559
DatabasesClient: &DatabasesClient,
5660
FirewallRulesClient: &FirewallRulesClient,
5761
FlexibleServerClient: &flexibleServerClient,
62+
FlexibleServerFirewallRulesClient: &flexibleServerFirewallRulesClient,
5863
FlexibleServerConfigurationsClient: &flexibleServerConfigurationsClient,
5964
ServersClient: &ServersClient,
6065
ServerKeysClient: &ServerKeysClient,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package mysql
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"time"
7+
8+
"github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2021-05-01/mysqlflexibleservers"
9+
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
10+
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
11+
azValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate"
12+
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
13+
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse"
14+
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/validate"
15+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
16+
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
17+
"github.com/hashicorp/terraform-provider-azurerm/utils"
18+
)
19+
20+
func resourceMySqlFlexibleServerFirewallRule() *pluginsdk.Resource {
21+
return &pluginsdk.Resource{
22+
Create: resourceMySqlFlexibleServerFirewallRuleCreateUpdate,
23+
Read: resourceMySqlFlexibleServerFirewallRuleRead,
24+
Update: resourceMySqlFlexibleServerFirewallRuleCreateUpdate,
25+
Delete: resourceMySqlFlexibleServerFirewallRuleDelete,
26+
27+
Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
28+
_, err := parse.FlexibleServerFirewallRuleID(id)
29+
return err
30+
}),
31+
32+
Timeouts: &pluginsdk.ResourceTimeout{
33+
Create: pluginsdk.DefaultTimeout(30 * time.Minute),
34+
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
35+
Update: pluginsdk.DefaultTimeout(30 * time.Minute),
36+
Delete: pluginsdk.DefaultTimeout(30 * time.Minute),
37+
},
38+
39+
Schema: map[string]*pluginsdk.Schema{
40+
"name": {
41+
Type: pluginsdk.TypeString,
42+
Required: true,
43+
ForceNew: true,
44+
},
45+
46+
"resource_group_name": azure.SchemaResourceGroupName(),
47+
48+
"server_name": {
49+
Type: pluginsdk.TypeString,
50+
Required: true,
51+
ForceNew: true,
52+
ValidateFunc: validate.FlexibleServerName,
53+
},
54+
55+
"start_ip_address": {
56+
Type: pluginsdk.TypeString,
57+
Required: true,
58+
ValidateFunc: azValidate.IPv4Address,
59+
},
60+
61+
"end_ip_address": {
62+
Type: pluginsdk.TypeString,
63+
Required: true,
64+
ValidateFunc: azValidate.IPv4Address,
65+
},
66+
},
67+
}
68+
}
69+
70+
func resourceMySqlFlexibleServerFirewallRuleCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
71+
client := meta.(*clients.Client).MySQL.FlexibleServerFirewallRulesClient
72+
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
73+
ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
74+
defer cancel()
75+
76+
log.Printf("[INFO] preparing arguments for AzureRM MySQL Flexible Server Firewall Rule creation.")
77+
startIPAddress := d.Get("start_ip_address").(string)
78+
endIPAddress := d.Get("end_ip_address").(string)
79+
80+
id := parse.NewFlexibleServerFirewallRuleID(subscriptionId, d.Get("resource_group_name").(string), d.Get("server_name").(string), d.Get("name").(string))
81+
if d.IsNewResource() {
82+
existing, err := client.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName)
83+
if err != nil {
84+
if !utils.ResponseWasNotFound(existing.Response) {
85+
return fmt.Errorf("checking for presence of existing %s: %v", id, err)
86+
}
87+
}
88+
89+
if !utils.ResponseWasNotFound(existing.Response) {
90+
return tf.ImportAsExistsError("azurerm_mysql_flexible_server_firewall_rule", id.ID())
91+
}
92+
}
93+
94+
properties := mysqlflexibleservers.FirewallRule{
95+
FirewallRuleProperties: &mysqlflexibleservers.FirewallRuleProperties{
96+
StartIPAddress: utils.String(startIPAddress),
97+
EndIPAddress: utils.String(endIPAddress),
98+
},
99+
}
100+
101+
future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName, properties)
102+
if err != nil {
103+
return fmt.Errorf("creating/updating %s: %v", id, err)
104+
}
105+
106+
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
107+
return fmt.Errorf("waiting for create/update of %s: %v", id, err)
108+
}
109+
110+
d.SetId(id.ID())
111+
return resourceMySqlFlexibleServerFirewallRuleRead(d, meta)
112+
}
113+
114+
func resourceMySqlFlexibleServerFirewallRuleRead(d *pluginsdk.ResourceData, meta interface{}) error {
115+
client := meta.(*clients.Client).MySQL.FlexibleServerFirewallRulesClient
116+
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
117+
defer cancel()
118+
119+
id, err := parse.FlexibleServerFirewallRuleID(d.Id())
120+
if err != nil {
121+
return err
122+
}
123+
124+
resp, err := client.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName)
125+
if err != nil {
126+
if utils.ResponseWasNotFound(resp.Response) {
127+
d.SetId("")
128+
return nil
129+
}
130+
return fmt.Errorf("retrieving %s: %+v", *id, err)
131+
}
132+
133+
d.Set("name", id.FirewallRuleName)
134+
d.Set("server_name", id.FlexibleServerName)
135+
d.Set("resource_group_name", id.ResourceGroup)
136+
137+
d.Set("start_ip_address", resp.StartIPAddress)
138+
d.Set("end_ip_address", resp.EndIPAddress)
139+
140+
return nil
141+
}
142+
143+
func resourceMySqlFlexibleServerFirewallRuleDelete(d *pluginsdk.ResourceData, meta interface{}) error {
144+
client := meta.(*clients.Client).MySQL.FlexibleServerFirewallRulesClient
145+
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
146+
defer cancel()
147+
148+
id, err := parse.FlexibleServerFirewallRuleID(d.Id())
149+
if err != nil {
150+
return err
151+
}
152+
153+
future, err := client.Delete(ctx, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName)
154+
if err != nil {
155+
return fmt.Errorf("deleting %s: %+v", *id, err)
156+
}
157+
158+
if err := future.WaitForCompletionRef(ctx, client.Client); err != nil {
159+
return fmt.Errorf("waiting for deletion of %s: %+v", *id, err)
160+
}
161+
162+
return nil
163+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package mysql_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
9+
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
10+
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
11+
"github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse"
12+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
13+
"github.com/hashicorp/terraform-provider-azurerm/utils"
14+
)
15+
16+
type MySQLFlexibleServerFirewallRuleResource struct {
17+
}
18+
19+
func TestAccMySQLFlexibleServerFirewallRule_basic(t *testing.T) {
20+
data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server_firewall_rule", "test")
21+
r := MySQLFlexibleServerFirewallRuleResource{}
22+
23+
data.ResourceTest(t, r, []acceptance.TestStep{
24+
{
25+
Config: r.basic(data),
26+
Check: acceptance.ComposeTestCheckFunc(
27+
check.That(data.ResourceName).ExistsInAzure(r),
28+
),
29+
},
30+
data.ImportStep(),
31+
})
32+
}
33+
34+
func TestAccMySQLFlexibleServerFirewallRule_requiresImport(t *testing.T) {
35+
data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server_firewall_rule", "test")
36+
r := MySQLFlexibleServerFirewallRuleResource{}
37+
38+
data.ResourceTest(t, r, []acceptance.TestStep{
39+
{
40+
Config: r.basic(data),
41+
Check: acceptance.ComposeTestCheckFunc(
42+
check.That(data.ResourceName).ExistsInAzure(r),
43+
),
44+
},
45+
data.RequiresImportErrorStep(r.requiresImport),
46+
})
47+
}
48+
49+
func (t MySQLFlexibleServerFirewallRuleResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
50+
id, err := parse.FlexibleServerFirewallRuleID(state.ID)
51+
if err != nil {
52+
return nil, err
53+
}
54+
55+
resp, err := clients.MySQL.FlexibleServerFirewallRulesClient.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
return utils.Bool(resp.Name != nil), nil
61+
}
62+
63+
func (MySQLFlexibleServerFirewallRuleResource) basic(data acceptance.TestData) string {
64+
return fmt.Sprintf(`
65+
provider "azurerm" {
66+
features {}
67+
}
68+
69+
resource "azurerm_resource_group" "test" {
70+
name = "acctestRG-%d"
71+
location = "%s"
72+
}
73+
74+
resource "azurerm_mysql_flexible_server" "test" {
75+
name = "acctest-fs-%d"
76+
resource_group_name = azurerm_resource_group.test.name
77+
location = azurerm_resource_group.test.location
78+
administrator_login = "adminTerraform"
79+
administrator_password = "QAZwsx123"
80+
sku_name = "B_Standard_B1s"
81+
}
82+
83+
resource "azurerm_mysql_flexible_server_firewall_rule" "test" {
84+
name = "acctestfwrule-%d"
85+
resource_group_name = azurerm_resource_group.test.name
86+
server_name = azurerm_mysql_flexible_server.test.name
87+
start_ip_address = "0.0.0.0"
88+
end_ip_address = "255.255.255.255"
89+
}
90+
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger)
91+
}
92+
93+
func (r MySQLFlexibleServerFirewallRuleResource) requiresImport(data acceptance.TestData) string {
94+
return fmt.Sprintf(`
95+
%s
96+
97+
resource "azurerm_mysql_flexible_server_firewall_rule" "import" {
98+
name = azurerm_mysql_flexible_server_firewall_rule.test.name
99+
resource_group_name = azurerm_mysql_flexible_server_firewall_rule.test.resource_group_name
100+
server_name = azurerm_mysql_flexible_server_firewall_rule.test.server_name
101+
start_ip_address = azurerm_mysql_flexible_server_firewall_rule.test.start_ip_address
102+
end_ip_address = azurerm_mysql_flexible_server_firewall_rule.test.end_ip_address
103+
}
104+
`, r.basic(data))
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package parse
2+
3+
// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
4+
5+
import (
6+
"fmt"
7+
"strings"
8+
9+
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
10+
)
11+
12+
type FlexibleServerFirewallRuleId struct {
13+
SubscriptionId string
14+
ResourceGroup string
15+
FlexibleServerName string
16+
FirewallRuleName string
17+
}
18+
19+
func NewFlexibleServerFirewallRuleID(subscriptionId, resourceGroup, flexibleServerName, firewallRuleName string) FlexibleServerFirewallRuleId {
20+
return FlexibleServerFirewallRuleId{
21+
SubscriptionId: subscriptionId,
22+
ResourceGroup: resourceGroup,
23+
FlexibleServerName: flexibleServerName,
24+
FirewallRuleName: firewallRuleName,
25+
}
26+
}
27+
28+
func (id FlexibleServerFirewallRuleId) String() string {
29+
segments := []string{
30+
fmt.Sprintf("Firewall Rule Name %q", id.FirewallRuleName),
31+
fmt.Sprintf("Flexible Server Name %q", id.FlexibleServerName),
32+
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
33+
}
34+
segmentsStr := strings.Join(segments, " / ")
35+
return fmt.Sprintf("%s: (%s)", "Flexible Server Firewall Rule", segmentsStr)
36+
}
37+
38+
func (id FlexibleServerFirewallRuleId) ID() string {
39+
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.DBforMySQL/flexibleServers/%s/firewallRules/%s"
40+
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FlexibleServerName, id.FirewallRuleName)
41+
}
42+
43+
// FlexibleServerFirewallRuleID parses a FlexibleServerFirewallRule ID into an FlexibleServerFirewallRuleId struct
44+
func FlexibleServerFirewallRuleID(input string) (*FlexibleServerFirewallRuleId, error) {
45+
id, err := azure.ParseAzureResourceID(input)
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
resourceId := FlexibleServerFirewallRuleId{
51+
SubscriptionId: id.SubscriptionID,
52+
ResourceGroup: id.ResourceGroup,
53+
}
54+
55+
if resourceId.SubscriptionId == "" {
56+
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
57+
}
58+
59+
if resourceId.ResourceGroup == "" {
60+
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
61+
}
62+
63+
if resourceId.FlexibleServerName, err = id.PopSegment("flexibleServers"); err != nil {
64+
return nil, err
65+
}
66+
if resourceId.FirewallRuleName, err = id.PopSegment("firewallRules"); err != nil {
67+
return nil, err
68+
}
69+
70+
if err := id.ValidateNoEmptySegments(input); err != nil {
71+
return nil, err
72+
}
73+
74+
return &resourceId, nil
75+
}

0 commit comments

Comments
 (0)