Skip to content

Commit

Permalink
Bug Fix: azurerm_app_service_plan and azurerm_app_service_slot cr…
Browse files Browse the repository at this point in the history
…ash fixes (#4184)
  • Loading branch information
mbfrahry authored Aug 30, 2019
1 parent a8ba985 commit f28a266
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 35 deletions.
79 changes: 58 additions & 21 deletions azurerm/helpers/azure/app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,23 @@ func SchemaAppServiceSiteConfig() *schema.Schema {
Schema: map[string]*schema.Schema{
"ip_address": {
Type: schema.TypeString,
Required: true,
Optional: true,
},
"virtual_network_subnet_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
},
"subnet_mask": {
Type: schema.TypeString,
Optional: true,
Default: "255.255.255.255",
Computed: true,
// TODO we should fix this in 2.0
// This attribute was made with the assumption that `ip_address` was the only valid option
// but `virtual_network_subnet_id` is being added and doesn't need a `subnet_mask`.
// We'll assume a default of "255.255.255.255" in the expand code when `ip_address` is specified
// and `subnet_mask` is not.
// Default: "255.255.255.255",
},
},
},
Expand Down Expand Up @@ -646,6 +657,10 @@ func SchemaAppServiceDataSourceSiteConfig() *schema.Schema {
Type: schema.TypeString,
Computed: true,
},
"virtual_network_subnet_id": {
Type: schema.TypeString,
Computed: true,
},
"subnet_mask": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -1294,12 +1309,12 @@ func FlattenAppServiceIdentity(identity *web.ManagedServiceIdentity) []interface
return []interface{}{result}
}

func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig {
func ExpandAppServiceSiteConfig(input interface{}) (*web.SiteConfig, error) {
configs := input.([]interface{})
siteConfig := web.SiteConfig{}
siteConfig := &web.SiteConfig{}

if len(configs) == 0 {
return siteConfig
return siteConfig, nil
}

config := configs[0].(map[string]interface{})
Expand Down Expand Up @@ -1354,26 +1369,45 @@ func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig {
if v, ok := config["ip_restriction"]; ok {
ipSecurityRestrictions := v.([]interface{})
restrictions := make([]web.IPSecurityRestriction, 0)
for _, ipSecurityRestriction := range ipSecurityRestrictions {
for i, ipSecurityRestriction := range ipSecurityRestrictions {
restriction := ipSecurityRestriction.(map[string]interface{})

ipAddress := restriction["ip_address"].(string)
mask := restriction["subnet_mask"].(string)
// the 2018-02-01 API expects a blank subnet mask and an IP address in CIDR format: a.b.c.d/x
// so translate the IP and mask if necessary
restrictionMask := ""
cidrAddress := ipAddress
if mask != "" {
ipNet := net.IPNet{IP: net.ParseIP(ipAddress), Mask: net.IPMask(net.ParseIP(mask))}
cidrAddress = ipNet.String()
} else if !strings.Contains(ipAddress, "/") {
cidrAddress += "/32"
vNetSubnetID := restriction["virtual_network_subnet_id"].(string)
if vNetSubnetID != "" && ipAddress != "" {
return siteConfig, fmt.Errorf(fmt.Sprintf("only one of `ip_address` or `virtual_network_subnet_id` can set set for `site_config.0.ip_restriction.%d`", i))
}

if vNetSubnetID == "" && ipAddress == "" {
return siteConfig, fmt.Errorf(fmt.Sprintf("one of `ip_address` or `virtual_network_subnet_id` must be set set for `site_config.0.ip_restriction.%d`", i))
}

restrictions = append(restrictions, web.IPSecurityRestriction{
IPAddress: &cidrAddress,
SubnetMask: &restrictionMask,
})
ipSecurityRestriction := web.IPSecurityRestriction{}
if ipAddress != "" {
mask := restriction["subnet_mask"].(string)
if mask == "" {
mask = "255.255.255.255"
}
// the 2018-02-01 API expects a blank subnet mask and an IP address in CIDR format: a.b.c.d/x
// so translate the IP and mask if necessary
restrictionMask := ""
cidrAddress := ipAddress
if mask != "" {
ipNet := net.IPNet{IP: net.ParseIP(ipAddress), Mask: net.IPMask(net.ParseIP(mask))}
cidrAddress = ipNet.String()
} else if !strings.Contains(ipAddress, "/") {
cidrAddress += "/32"
}
ipSecurityRestriction.IPAddress = &cidrAddress
ipSecurityRestriction.SubnetMask = &restrictionMask
}

if vNetSubnetID != "" {
ipSecurityRestriction.VnetSubnetResourceID = &vNetSubnetID
}

restrictions = append(restrictions, ipSecurityRestriction)

}
siteConfig.IPSecurityRestrictions = &restrictions
}
Expand Down Expand Up @@ -1432,7 +1466,7 @@ func ExpandAppServiceSiteConfig(input interface{}) web.SiteConfig {
siteConfig.Cors = &expand
}

return siteConfig
return siteConfig, nil
}

func FlattenAppServiceSiteConfig(input *web.SiteConfig) []interface{} {
Expand Down Expand Up @@ -1500,6 +1534,9 @@ func FlattenAppServiceSiteConfig(input *web.SiteConfig) []interface{} {
if subnet := v.SubnetMask; subnet != nil {
block["subnet_mask"] = *subnet
}
if vNetSubnetID := v.VnetSubnetResourceID; vNetSubnetID != nil {
block["virtual_network_subnet_id"] = *vNetSubnetID
}
restrictions = append(restrictions, block)
}
}
Expand Down
22 changes: 16 additions & 6 deletions azurerm/resource_arm_app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,10 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error
httpsOnly := d.Get("https_only").(bool)
t := d.Get("tags").(map[string]interface{})

siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service %q (Resource Group %q): %s", name, resGroup, err)
}

siteEnvelope := web.Site{
Location: &location,
Expand All @@ -226,7 +229,7 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error
ServerFarmID: utils.String(appServicePlanId),
Enabled: utils.Bool(enabled),
HTTPSOnly: utils.Bool(httpsOnly),
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
},
}

Expand Down Expand Up @@ -316,15 +319,19 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
httpsOnly := d.Get("https_only").(bool)
t := d.Get("tags").(map[string]interface{})

siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service %q (Resource Group %q): %s", name, resGroup, err)
}

siteEnvelope := web.Site{
Location: &location,
Tags: tags.Expand(t),
SiteProperties: &web.SiteProperties{
ServerFarmID: utils.String(appServicePlanId),
Enabled: utils.Bool(enabled),
HTTPSOnly: utils.Bool(httpsOnly),
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
},
}

Expand All @@ -344,9 +351,12 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error

if d.HasChange("site_config") {
// update the main configuration
siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service %q (Resource Group %q): %s", name, resGroup, err)
}
siteConfigResource := web.SiteConfigResource{
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
}

if _, err := client.CreateOrUpdateConfiguration(ctx, resGroup, name, siteConfigResource); err != nil {
Expand Down
21 changes: 15 additions & 6 deletions azurerm/resource_arm_app_service_slot.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,18 @@ func resourceArmAppServiceSlotCreate(d *schema.ResourceData, meta interface{}) e
t := d.Get("tags").(map[string]interface{})
affinity := d.Get("client_affinity_enabled").(bool)

siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service Slot %q (Resource Group %q): %s", slot, resourceGroup, err)
}
siteEnvelope := web.Site{
Location: &location,
Tags: tags.Expand(t),
SiteProperties: &web.SiteProperties{
ServerFarmID: utils.String(appServicePlanId),
Enabled: utils.Bool(enabled),
HTTPSOnly: utils.Bool(httpsOnly),
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
ClientAffinityEnabled: &affinity,
},
}
Expand Down Expand Up @@ -230,7 +233,10 @@ func resourceArmAppServiceSlotUpdate(d *schema.ResourceData, meta interface{}) e

location := azure.NormalizeLocation(d.Get("location").(string))
appServicePlanId := d.Get("app_service_plan_id").(string)
siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service Slot %q (Resource Group %q): %s", slot, resourceGroup, err)
}
enabled := d.Get("enabled").(bool)
httpsOnly := d.Get("https_only").(bool)
t := d.Get("tags").(map[string]interface{})
Expand All @@ -242,7 +248,7 @@ func resourceArmAppServiceSlotUpdate(d *schema.ResourceData, meta interface{}) e
ServerFarmID: utils.String(appServicePlanId),
Enabled: utils.Bool(enabled),
HTTPSOnly: utils.Bool(httpsOnly),
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
},
}
if v, ok := d.GetOk("client_affinity_enabled"); ok {
Expand All @@ -261,9 +267,12 @@ func resourceArmAppServiceSlotUpdate(d *schema.ResourceData, meta interface{}) e

if d.HasChange("site_config") {
// update the main configuration
siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
siteConfig, err := azure.ExpandAppServiceSiteConfig(d.Get("site_config"))
if err != nil {
return fmt.Errorf("Error expanding `site_config` for App Service Slot %q (Resource Group %q): %s", slot, resourceGroup, err)
}
siteConfigResource := web.SiteConfigResource{
SiteConfig: &siteConfig,
SiteConfig: siteConfig,
}
if _, err := client.CreateOrUpdateConfigurationSlot(ctx, resourceGroup, appServiceName, siteConfigResource, slot); err != nil {
return fmt.Errorf("Error updating Configuration for App Service Slot %q/%q: %+v", appServiceName, slot, err)
Expand Down
80 changes: 80 additions & 0 deletions azurerm/resource_arm_app_service_slot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,31 @@ func TestAccAzureRMAppServiceSlot_oneIpRestriction(t *testing.T) {
})
}

func TestAccAzureRMAppServiceSlot_oneVNetSubnetIpRestriction(t *testing.T) {
resourceName := "azurerm_app_service_slot.test"
ri := tf.AccRandTimeInt()
config := testAccAzureRMAppServiceSlot_oneVNetSubnetIpRestriction(ri, testLocation())

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMAppServiceSlotDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMAppServiceSlotExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMAppServiceSlot_zeroedIpRestriction(t *testing.T) {
resourceName := "azurerm_app_service_slot.test"
ri := tf.AccRandTimeInt()
Expand Down Expand Up @@ -2739,6 +2764,61 @@ resource "azurerm_app_service_slot" "test" {
`, rInt, location, rInt, rInt, rInt)
}

func testAccAzureRMAppServiceSlot_oneVNetSubnetIpRestriction(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%d"
address_space = ["10.0.0.0/16"]
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
}
resource "azurerm_subnet" "test" {
name = "acctestsubnet%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.2.0/24"
}
resource "azurerm_app_service_plan" "test" {
name = "acctestASP-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "test" {
name = "acctestAS-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
app_service_plan_id = "${azurerm_app_service_plan.test.id}"
}
resource "azurerm_app_service_slot" "test" {
name = "acctestASSlot-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
app_service_plan_id = "${azurerm_app_service_plan.test.id}"
app_service_name = "${azurerm_app_service.test.name}"
site_config {
ip_restriction {
virtual_network_subnet_id = "${azurerm_subnet.test.id}"
}
}
}
`, rInt, location, rInt, rInt, rInt, rInt, rInt)
}

func testAccAzureRMAppServiceSlot_zeroedIpRestriction(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
Loading

0 comments on commit f28a266

Please sign in to comment.