Skip to content
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

App Service / Function Apps: support for updating #1125

Merged
merged 6 commits into from Apr 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 29 additions & 11 deletions azurerm/resource_arm_app_service.go
Expand Up @@ -185,20 +185,12 @@ func resourceArmAppService() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
Default: false,

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
ForceNew: true,
},

"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: true,

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
ForceNew: true,
},

"app_settings": {
Expand Down Expand Up @@ -243,9 +235,7 @@ func resourceArmAppService() *schema.Resource {
},
},

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
"tags": tagsForceNewSchema(),
"tags": tagsSchema(),

"site_credential": {
Type: schema.TypeList,
Expand Down Expand Up @@ -376,6 +366,34 @@ func resourceArmAppServiceUpdate(d *schema.ResourceData, meta interface{}) error
resGroup := id.ResourceGroup
name := id.Path["sites"]

location := azureRMNormalizeLocation(d.Get("location").(string))
appServicePlanId := d.Get("app_service_plan_id").(string)
enabled := d.Get("enabled").(bool)
httpsOnly := d.Get("https_only").(bool)
tags := d.Get("tags").(map[string]interface{})

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

future, err := client.CreateOrUpdate(ctx, resGroup, name, siteEnvelope)
if err != nil {
return err
}

err = future.WaitForCompletion(ctx, client.Client)
if err != nil {
return err
}

if d.HasChange("site_config") {
// update the main configuration
siteConfig := expandAppServiceSiteConfig(d)
Expand Down
66 changes: 42 additions & 24 deletions azurerm/resource_arm_function_app.go
Expand Up @@ -44,10 +44,6 @@ func resourceArmFunctionApp() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
Default: true,

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
ForceNew: true,
},

"version": {
Expand Down Expand Up @@ -108,9 +104,7 @@ func resourceArmFunctionApp() *schema.Resource {
},
},

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
"tags": tagsForceNewSchema(),
"tags": tagsSchema(),

"default_hostname": {
Type: schema.TypeString,
Expand All @@ -126,20 +120,12 @@ func resourceArmFunctionApp() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
Computed: true,

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
ForceNew: true,
},

"https_only": {
Type: schema.TypeBool,
Optional: true,
Default: false,

// TODO: (tombuildsstuff) support Update once the API is fixed:
// https://github.com/Azure/azure-rest-api-specs/issues/1697
ForceNew: true,
},

"site_config": {
Expand Down Expand Up @@ -252,16 +238,48 @@ func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) erro
resGroup := id.ResourceGroup
name := id.Path["sites"]

if d.HasChange("app_settings") || d.HasChange("version") {
appSettings := expandFunctionAppAppSettings(d)
settings := web.StringDictionary{
Properties: appSettings,
}
location := azureRMNormalizeLocation(d.Get("location").(string))
kind := "functionapp"
appServicePlanID := d.Get("app_service_plan_id").(string)
enabled := d.Get("enabled").(bool)
clientAffinityEnabled := d.Get("client_affinity_enabled").(bool)
httpsOnly := d.Get("https_only").(bool)
tags := d.Get("tags").(map[string]interface{})
basicAppSettings := getBasicFunctionAppAppSettings(d)
siteConfig := expandFunctionAppSiteConfig(d)
siteConfig.AppSettings = &basicAppSettings

_, err := client.UpdateApplicationSettings(ctx, resGroup, name, settings)
if err != nil {
return fmt.Errorf("Error updating Application Settings for Function App %q: %+v", name, err)
}
siteEnvelope := web.Site{
Kind: &kind,
Location: &location,
Tags: expandTags(tags),
SiteProperties: &web.SiteProperties{
ServerFarmID: utils.String(appServicePlanID),
Enabled: utils.Bool(enabled),
ClientAffinityEnabled: utils.Bool(clientAffinityEnabled),
HTTPSOnly: utils.Bool(httpsOnly),
SiteConfig: &siteConfig,
},
}

future, err := client.CreateOrUpdate(ctx, resGroup, name, siteEnvelope)
if err != nil {
return err
}

err = future.WaitForCompletion(ctx, client.Client)
if err != nil {
return err
}

appSettings := expandFunctionAppAppSettings(d)
settings := web.StringDictionary{
Properties: appSettings,
}

_, err = client.UpdateApplicationSettings(ctx, resGroup, name, settings)
if err != nil {
return fmt.Errorf("Error updating Application Settings for Function App %q: %+v", name, err)
}

if d.HasChange("site_config") {
Expand Down
72 changes: 72 additions & 0 deletions azurerm/resource_arm_function_app_test.go
Expand Up @@ -56,6 +56,39 @@ func TestAccAzureRMFunctionApp_tags(t *testing.T) {
})
}

func TestAccAzureRMFunctionApp_tagsUpdate(t *testing.T) {
resourceName := "azurerm_function_app.test"
ri := acctest.RandInt()
rs := strings.ToLower(acctest.RandString(11))
config := testAccAzureRMFunctionApp_tags(ri, rs, testLocation())
updatedConfig := testAccAzureRMFunctionApp_tagsUpdated(ri, rs, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMFunctionAppDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMFunctionAppExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.environment", "production"),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMFunctionAppExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags.environment", "production"),
resource.TestCheckResourceAttr(resourceName, "tags.hello", "Berlin"),
),
},
},
})
}

func TestAccAzureRMFunctionApp_appSettings(t *testing.T) {
resourceName := "azurerm_function_app.test"
ri := acctest.RandInt()
Expand Down Expand Up @@ -428,6 +461,45 @@ resource "azurerm_function_app" "test" {
`, rInt, location, storage)
}

func testAccAzureRMFunctionApp_tagsUpdated(rInt int, storage string, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%[1]d"
location = "%[2]s"
}

resource "azurerm_storage_account" "test" {
name = "acctestsa%[3]s"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_app_service_plan" "test" {
name = "acctestASP-%[1]d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
tier = "Standard"
size = "S1"
}
}

resource "azurerm_function_app" "test" {
name = "acctest-%[1]d-func"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
app_service_plan_id = "${azurerm_app_service_plan.test.id}"
storage_connection_string = "${azurerm_storage_account.test.primary_connection_string}"
tags {
environment = "production"
hello = "Berlin"
}
}
`, rInt, location, storage)
}

func testAccAzureRMFunctionApp_version(rInt int, storage string, location string, version string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
6 changes: 3 additions & 3 deletions website/docs/r/app_service.html.markdown
Expand Up @@ -121,15 +121,15 @@ The following arguments are supported:

* `connection_string` - (Optional) An `connection_string` block as defined below.

* `client_affinity_enabled` - (Optional) Should the App Service send session affinity cookies, which route client requests in the same session to the same instance? Changing this forces a new resource to be created.
* `client_affinity_enabled` - (Optional) Should the App Service send session affinity cookies, which route client requests in the same session to the same instance?

* `enabled` - (Optional) Is the App Service Enabled? Changing this forces a new resource to be created.

* `https_only` - (Optional) Can the App Service only be accessed via HTTPS? Defaults to `false`. Changing this forces a new resource to be created.
* `https_only` - (Optional) Can the App Service only be accessed via HTTPS? Defaults to `false`.

* `site_config` - (Optional) A `site_config` object as defined below.

* `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created.
* `tags` - (Optional) A mapping of tags to assign to the resource.

---

Expand Down
8 changes: 4 additions & 4 deletions website/docs/r/function_app.html.markdown
Expand Up @@ -101,17 +101,17 @@ The following arguments are supported:

* `connection_string` - (Optional) An `connection_string` block as defined below.

* `client_affinity_enabled` - (Optional) Should the Function App send session affinity cookies, which route client requests in the same session to the same instance? Changing this forces a new resource to be created.
* `client_affinity_enabled` - (Optional) Should the Function App send session affinity cookies, which route client requests in the same session to the same instance?

* `enabled` - (Optional) Is the Function App enabled? Changing this forces a new resource to be created.
* `enabled` - (Optional) Is the Function App enabled?

* `https_only` - (Optional) Can the Function App only be accessed via HTTPS? Defaults to `false`. Changing this forces a new resource to be created.
* `https_only` - (Optional) Can the Function App only be accessed via HTTPS? Defaults to `false`.

* `version` - (Optional) The runtime version associated with the Function App. Possible values are `~1` and `beta`. Defaults to `~1`.

* `site_config` - (Optional) A `site_config` object as defined below.

* `tags` - (Optional) A mapping of tags to assign to the resource. Changing this forces a new resource to be created.
* `tags` - (Optional) A mapping of tags to assign to the resource.

---

Expand Down