Skip to content

Commit

Permalink
App Service: support for both Timeouts and requiring Import before Up…
Browse files Browse the repository at this point in the history
…sert
  • Loading branch information
tombuildsstuff committed Aug 9, 2018
1 parent 49c0584 commit bb7edd4
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 28 deletions.
50 changes: 39 additions & 11 deletions azurerm/resource_arm_app_service.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package azurerm

import (
"context"
"fmt"
"log"
"regexp"
"time"

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand All @@ -21,6 +24,11 @@ func resourceArmAppService() *schema.Resource {
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(time.Minute * 30),
Update: schema.DefaultTimeout(time.Minute * 30),
Delete: schema.DefaultTimeout(time.Minute * 30),
},

Schema: map[string]*schema.Schema{
"name": {
Expand Down Expand Up @@ -188,6 +196,21 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error
log.Printf("[INFO] preparing arguments for AzureRM App Service creation.")

name := d.Get("name").(string)
resGroup := d.Get("resource_group_name").(string)

// first check if there's one in this subscription requiring import
resp, err := client.Get(ctx, resGroup, name)
if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error checking for the existence of App Service %q (Resource Group %q): %+v", name, resGroup, err)
}
}

if resp.ID != nil {
return tf.ImportAsExistsError("azurerm_app_service", *resp.ID)
}

// then check the name's globally unique
availabilityRequest := web.ResourceNameAvailabilityRequest{
Name: utils.String(name),
Type: web.CheckNameResourceTypesMicrosoftWebsites,
Expand All @@ -201,7 +224,6 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("The name %q used for the App Service needs to be globally unique and isn't available: %s", name, *available.Message)
}

resGroup := d.Get("resource_group_name").(string)
location := azureRMNormalizeLocation(d.Get("location").(string))
appServicePlanId := d.Get("app_service_plan_id").(string)
enabled := d.Get("enabled").(bool)
Expand Down Expand Up @@ -236,7 +258,9 @@ func resourceArmAppServiceCreate(d *schema.ResourceData, meta interface{}) error
return err
}

err = createFuture.WaitForCompletionRef(ctx, client.Client)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutCreate))
defer cancel()
err = createFuture.WaitForCompletionRef(waitCtx, client.Client)
if err != nil {
return err
}
Expand Down Expand Up @@ -289,7 +313,9 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
return err
}

err = future.WaitForCompletionRef(ctx, client.Client)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutUpdate))
defer cancel()
err = future.WaitForCompletionRef(waitCtx, client.Client)
if err != nil {
return err
}
Expand All @@ -300,7 +326,7 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
siteConfigResource := web.SiteConfigResource{
SiteConfig: &siteConfig,
}
_, err := client.CreateOrUpdateConfiguration(ctx, resGroup, name, siteConfigResource)
_, err := client.CreateOrUpdateConfiguration(waitCtx, resGroup, name, siteConfigResource)
if err != nil {
return fmt.Errorf("Error updating Configuration for App Service %q: %+v", name, err)
}
Expand All @@ -317,7 +343,7 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
},
}

_, err := client.Update(ctx, resGroup, name, sitePatchResource)
_, err := client.Update(waitCtx, resGroup, name, sitePatchResource)
if err != nil {
return fmt.Errorf("Error updating App Service ARR Affinity setting %q: %+v", name, err)
}
Expand All @@ -330,7 +356,7 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
Properties: appSettings,
}

_, err := client.UpdateApplicationSettings(ctx, resGroup, name, settings)
_, err := client.UpdateApplicationSettings(waitCtx, resGroup, name, settings)
if err != nil {
return fmt.Errorf("Error updating Application Settings for App Service %q: %+v", name, err)
}
Expand All @@ -343,28 +369,28 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
Properties: connectionStrings,
}

_, err := client.UpdateConnectionStrings(ctx, resGroup, name, properties)
_, err := client.UpdateConnectionStrings(waitCtx, resGroup, name, properties)
if err != nil {
return fmt.Errorf("Error updating Connection Strings for App Service %q: %+v", name, err)
}
}

if d.HasChange("identity") {
site, err := client.Get(ctx, resGroup, name)
site, err := client.Get(waitCtx, resGroup, name)
if err != nil {
return fmt.Errorf("Error getting configuration for App Service %q: %+v", name, err)
}

appServiceIdentity := expandAzureRmAppServiceIdentity(d)
site.Identity = appServiceIdentity

future, err := client.CreateOrUpdate(ctx, resGroup, name, site)
future, err := client.CreateOrUpdate(waitCtx, resGroup, name, site)

if err != nil {
return fmt.Errorf("Error updating Managed Service Identity for App Service %q: %+v", name, err)
}

err = future.WaitForCompletionRef(ctx, client.Client)
err = future.WaitForCompletionRef(waitCtx, client.Client)

if err != nil {
return fmt.Errorf("Error updating Managed Service Identity for App Service %q: %+v", name, err)
Expand Down Expand Up @@ -491,7 +517,9 @@ func resourceArmAppServiceDelete(d *schema.ResourceData, meta interface{}) error
deleteMetrics := true
deleteEmptyServerFarm := false
ctx := meta.(*ArmClient).StopContext
resp, err := client.Delete(ctx, resGroup, name, &deleteMetrics, &deleteEmptyServerFarm)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutDelete))
defer cancel()
resp, err := client.Delete(waitCtx, resGroup, name, &deleteMetrics, &deleteEmptyServerFarm)
if err != nil {
if !utils.ResponseWasNotFound(resp) {
return err
Expand Down
27 changes: 25 additions & 2 deletions azurerm/resource_arm_app_service_custom_hostname_binding.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package azurerm

import (
"context"
"fmt"
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web"
"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand All @@ -17,6 +20,10 @@ func resourceArmAppServiceCustomHostnameBinding() *schema.Resource {
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(time.Minute * 10),
Delete: schema.DefaultTimeout(time.Minute * 10),
},

Schema: map[string]*schema.Schema{
"hostname": {
Expand Down Expand Up @@ -46,12 +53,26 @@ func resourceArmAppServiceCustomHostnameBindingCreate(d *schema.ResourceData, me
appServiceName := d.Get("app_service_name").(string)
hostname := d.Get("hostname").(string)

// first check if there's one in this subscription requiring import
resp, err := client.GetHostNameBinding(ctx, resourceGroup, appServiceName, hostname)
if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error checking for the existence of Hostname Binding %q (App Service Name %q / Resource Group %q): %+v", hostname, appServiceName, resourceGroup, err)
}
}

if resp.ID != nil {
return tf.ImportAsExistsError("azurerm_app_service_custom_hostname_binding", *resp.ID)
}

properties := web.HostNameBinding{
HostNameBindingProperties: &web.HostNameBindingProperties{
SiteName: utils.String(appServiceName),
},
}
_, err := client.CreateOrUpdateHostNameBinding(ctx, resourceGroup, appServiceName, hostname, properties)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutCreate))
defer cancel()
_, err = client.CreateOrUpdateHostNameBinding(waitCtx, resourceGroup, appServiceName, hostname, properties)
if err != nil {
return err
}
Expand Down Expand Up @@ -113,7 +134,9 @@ func resourceArmAppServiceCustomHostnameBindingDelete(d *schema.ResourceData, me
log.Printf("[DEBUG] Deleting App Service Hostname Binding %q (App Service %q / Resource Group %q)", hostname, appServiceName, resGroup)

ctx := meta.(*ArmClient).StopContext
resp, err := client.DeleteHostNameBinding(ctx, resGroup, appServiceName, hostname)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutDelete))
defer cancel()
resp, err := client.DeleteHostNameBinding(waitCtx, resGroup, appServiceName, hostname)
if err != nil {
if !utils.ResponseWasNotFound(resp) {
return err
Expand Down
32 changes: 29 additions & 3 deletions azurerm/resource_arm_app_service_plan.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package azurerm

import (
"context"
"fmt"
"log"
"regexp"
"time"

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2018-02-01/web"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand All @@ -20,6 +23,11 @@ func resourceArmAppServicePlan() *schema.Resource {
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(time.Minute * 30),
Update: schema.DefaultTimeout(time.Minute * 30),
Delete: schema.DefaultTimeout(time.Minute * 30),
},

Schema: map[string]*schema.Schema{
"name": {
Expand Down Expand Up @@ -116,6 +124,21 @@ func resourceArmAppServicePlanCreateUpdate(d *schema.ResourceData, meta interfac

resGroup := d.Get("resource_group_name").(string)
name := d.Get("name").(string)

if d.IsNewResource() {
// first check if there's one in this subscription requiring import
resp, err := client.Get(ctx, resGroup, name)
if err != nil {
if !utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error checking for the existence of App Service Plan %q (Resource Group %q): %+v", name, resGroup, err)
}
}

if resp.ID != nil {
return tf.ImportAsExistsError("azurerm_app_service_plan", *resp.ID)
}
}

location := azureRMNormalizeLocation(d.Get("location").(string))
kind := d.Get("kind").(string)
tags := d.Get("tags").(map[string]interface{})
Expand All @@ -136,7 +159,9 @@ func resourceArmAppServicePlanCreateUpdate(d *schema.ResourceData, meta interfac
return err
}

err = createFuture.WaitForCompletionRef(ctx, client.Client)
waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(tf.TimeoutForCreateUpdate(d)))
defer cancel()
err = createFuture.WaitForCompletionRef(waitCtx, client.Client)
if err != nil {
return err
}
Expand Down Expand Up @@ -215,8 +240,9 @@ func resourceArmAppServicePlanDelete(d *schema.ResourceData, meta interface{}) e

log.Printf("[DEBUG] Deleting app service plan %s: %s", resGroup, name)

resp, err := client.Delete(ctx, resGroup, name)

waitCtx, cancel := context.WithTimeout(ctx, d.Timeout(schema.TimeoutDelete))
defer cancel()
resp, err := client.Delete(waitCtx, resGroup, name)
if err != nil {
if utils.ResponseWasNotFound(resp) {
return nil
Expand Down
Loading

0 comments on commit bb7edd4

Please sign in to comment.