From 25d20b36c12c8f05179f30e1da6320abab7b9694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Arild=20T=C3=B8rresdal?= Date: Tue, 23 Oct 2018 12:33:43 +0200 Subject: [PATCH] Support full site_config as with app_service. * Reference same schema as in AppService * Use Same expand/flatten as in AppService * Added integration test for ip_restrictions --- azurerm/resource_arm_function_app.go | 85 ++--------------------- azurerm/resource_arm_function_app_test.go | 63 +++++++++++++++++ website/docs/r/function_app.html.markdown | 40 ++++++++++- 3 files changed, 106 insertions(+), 82 deletions(-) diff --git a/azurerm/resource_arm_function_app.go b/azurerm/resource_arm_function_app.go index 4525f3668e44..27f62c8df96d 100644 --- a/azurerm/resource_arm_function_app.go +++ b/azurerm/resource_arm_function_app.go @@ -9,6 +9,7 @@ import ( "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/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -154,31 +155,7 @@ func resourceArmFunctionApp() *schema.Resource { Default: false, }, - "site_config": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "always_on": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "use_32_bit_worker_process": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "websockets_enabled": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - }, - }, - }, + "site_config": azure.SchemaAppServiceSiteConfig(), "site_credential": { Type: schema.TypeList, @@ -238,7 +215,7 @@ func resourceArmFunctionAppCreate(d *schema.ResourceData, meta interface{}) erro basicAppSettings := getBasicFunctionAppAppSettings(d, appServiceTier) - siteConfig := expandFunctionAppSiteConfig(d) + siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config")) siteConfig.AppSettings = &basicAppSettings siteEnvelope := web.Site{ @@ -309,7 +286,7 @@ func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) erro return err } basicAppSettings := getBasicFunctionAppAppSettings(d, appServiceTier) - siteConfig := expandFunctionAppSiteConfig(d) + siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config")) siteConfig.AppSettings = &basicAppSettings siteEnvelope := web.Site{ @@ -352,7 +329,7 @@ func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) erro } if d.HasChange("site_config") { - siteConfig := expandFunctionAppSiteConfig(d) + siteConfig := azure.ExpandAppServiceSiteConfig(d.Get("site_config")) siteConfigResource := web.SiteConfigResource{ SiteConfig: &siteConfig, } @@ -470,7 +447,7 @@ func resourceArmFunctionAppRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error making Read request on AzureRM Function App Configuration %q: %+v", name, err) } - siteConfig := flattenFunctionAppSiteConfig(configResp.SiteConfig) + siteConfig := azure.FlattenAppServiceSiteConfig(configResp.SiteConfig) if err := d.Set("site_config", siteConfig); err != nil { return err } @@ -574,56 +551,6 @@ func expandFunctionAppAppSettings(d *schema.ResourceData, appServiceTier string) return output } -func expandFunctionAppSiteConfig(d *schema.ResourceData) web.SiteConfig { - configs := d.Get("site_config").([]interface{}) - siteConfig := web.SiteConfig{} - - if len(configs) == 0 { - return siteConfig - } - - config := configs[0].(map[string]interface{}) - - if v, ok := config["always_on"]; ok { - siteConfig.AlwaysOn = utils.Bool(v.(bool)) - } - - if v, ok := config["use_32_bit_worker_process"]; ok { - siteConfig.Use32BitWorkerProcess = utils.Bool(v.(bool)) - } - - if v, ok := config["websockets_enabled"]; ok { - siteConfig.WebSocketsEnabled = utils.Bool(v.(bool)) - } - - return siteConfig -} - -func flattenFunctionAppSiteConfig(input *web.SiteConfig) []interface{} { - results := make([]interface{}, 0) - result := make(map[string]interface{}, 0) - - if input == nil { - log.Printf("[DEBUG] SiteConfig is nil") - return results - } - - if input.AlwaysOn != nil { - result["always_on"] = *input.AlwaysOn - } - - if input.Use32BitWorkerProcess != nil { - result["use_32_bit_worker_process"] = *input.Use32BitWorkerProcess - } - - if input.WebSocketsEnabled != nil { - result["websockets_enabled"] = *input.WebSocketsEnabled - } - - results = append(results, result) - return results -} - func expandFunctionAppConnectionStrings(d *schema.ResourceData) map[string]*web.ConnStringValueTypePair { input := d.Get("connection_string").([]interface{}) output := make(map[string]*web.ConnStringValueTypePair, len(input)) diff --git a/azurerm/resource_arm_function_app_test.go b/azurerm/resource_arm_function_app_test.go index cb5b78892920..b935cc9e5507 100644 --- a/azurerm/resource_arm_function_app_test.go +++ b/azurerm/resource_arm_function_app_test.go @@ -152,6 +152,29 @@ func TestAccAzureRMFunctionApp_siteConfig(t *testing.T) { }) } +func TestAccAzureRMFunctionApp_ipRestrictions(t *testing.T) { + resourceName := "azurerm_function_app.test" + ri := acctest.RandInt() + rs := strings.ToLower(acctest.RandString(11)) + config := testAccAzureRMFunctionApp_ipRestrictions(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, "site_config.0.ip_restriction.0.ip_address", "10.0.10.5"), + resource.TestCheckResourceAttr(resourceName, "site_config.0.ip_restriction.0.subnet_mask", "255.255.255.255"), + ), + }, + }, + }) +} + func TestAccAzureRMFunctionApp_connectionStrings(t *testing.T) { resourceName := "azurerm_function_app.test" ri := acctest.RandInt() @@ -771,6 +794,46 @@ resource "azurerm_function_app" "test" { `, rInt, location, rString) } +func testAccAzureRMFunctionApp_ipRestrictions(rInt int, rString, 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}" + site_config { + ip_restriction { + ip_address = "10.0.10.5" + } + } +} +`, rInt, location, rString) +} + func testAccAzureRMFunctionApp_connectionStrings(rInt int, rString, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/function_app.html.markdown b/website/docs/r/function_app.html.markdown index ddfadae55db3..ce89c7e112e8 100644 --- a/website/docs/r/function_app.html.markdown +++ b/website/docs/r/function_app.html.markdown @@ -127,15 +127,49 @@ The following arguments are supported: `site_config` supports the following: -* `always_on` - (Optional) Should the Function App be loaded at all times? Defaults to `false`. -* `use_32_bit_worker_process` - (Optional) Should the Function App run in 32 bit mode, rather than 64 bit mode? Defaults to `true`. +* `always_on` - (Optional) Should the app be loaded at all times? Defaults to `false`. +* `default_documents` - (Optional) The ordering of default documents to load, if an address isn't specified. +* `dotnet_framework_version` - (Optional) The version of the .net framework's CLR used in this App Service. Possible values are `v2.0` (which will use the latest version of the .net framework for the .net CLR v2 - currently `.net 3.5`) and `v4.0` (which corresponds to the latest version of the .net CLR v4 - which at the time of writing is `.net 4.7.1`). [For more information on which .net CLR version to use based on the .net framework you're targeting - please see this table](https://en.wikipedia.org/wiki/.NET_Framework_version_history#Overview). Defaults to `v4.0`. +* `http2_enabled` - (Optional) Is HTTP2 Enabled on this App Service? Defaults to `false`. +* `ftps_state` - (Optional) State of FTP / FTPS service for this AppService. Possible values include: `AllAllowed`, `FtpsOnly` and `Disabled`. +* `ip_restriction` - (Optional) One or more `ip_restriction` blocks as defined below. +* `java_version` - (Optional) The version of Java to use. If specified `java_container` and `java_container_version` must also be specified. Possible values are `1.7` and `1.8`. +* `java_container` - (Optional) The Java Container to use. If specified `java_version` and `java_container_version` must also be specified. Possible values are `JETTY` and `TOMCAT`. +* `java_container_version` - (Optional) The version of the Java Container to use. If specified `java_version` and `java_container` must also be specified. -~> **Note:** when using an App Service Plan in the `Free` or `Shared` Tiers `use_32_bit_worker_process` must be set to `true`. +* `local_mysql_enabled` - (Optional) Is "MySQL In App" Enabled? This runs a local MySQL instance with your app and shares resources from the App Service plan. + +~> **NOTE:** MySQL In App is not intended for production environments and will not scale beyond a single instance. Instead you may wish [to use Azure Database for MySQL](/docs/providers/azurerm/r/mysql_database.html). + +* `linux_fx_version` - (Optional) Linux App Framework and version for the AppService, e.g. `DOCKER|(golang:latest)`. +* `managed_pipeline_mode` - (Optional) The Managed Pipeline Mode. Possible values are `Integrated` and `Classic`. Defaults to `Integrated`. +* `min_tls_version` - (Optional) The minimum supported TLS version for the app service. Possible values are `1.0`, `1.1`, and `1.2`. Defaults to `1.2` for new app services. +* `php_version` - (Optional) The version of PHP to use in this App Service. Possible values are `5.5`, `5.6`, `7.0` and `7.1`. +* `python_version` - (Optional) The version of Python to use in this App Service. Possible values are `2.7` and `3.4`. +* `remote_debugging_enabled` - (Optional) Is Remote Debugging Enabled? Defaults to `false`. +* `remote_debugging_version` - (Optional) Which version of Visual Studio should the Remote Debugger be compatible with? Possible values are `VS2012`, `VS2013`, `VS2015` and `VS2017`. +* `scm_type` - (Optional) The type of Source Control enabled for this App Service. Possible values include `None` and `LocalGit`. Defaults to `None`. + +~> **NOTE:** Additional Source Control types will be added in the future, once support for them has been added in the Azure SDK for Go. + +* `use_32_bit_worker_process` - (Optional) Should the App Service run in 32 bit mode, rather than 64 bit mode? + +~> **NOTE:** when using an App Service Plan in the `Free` or `Shared` Tiers `use_32_bit_worker_process` must be set to `true`. + +* `virtual_network_name` - (Optional) The name of the Virtual Network which this App Service should be attached to. * `websockets_enabled` - (Optional) Should WebSockets be enabled? --- +`ip_restriction` supports the following: + +* `ip_address` - (Required) The IP Address used for this IP Restriction. + +* `subnet_mask` - (Optional) The Subnet mask used for this IP Restriction. Defaults to `255.255.255.255`. + +--- + `identity` supports the following: * `type` - (Required) Specifies the identity type of the App Service. At this time the only allowed value is `SystemAssigned`.