diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_action_group_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_action_group_test.go index e418163df465..aab0ebf9972a 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_action_group_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_action_group_test.go @@ -356,11 +356,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctestFA-%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}" - storage_connection_string = "${azurerm_storage_account.test.primary_connection_string}" + name = "acctestFA-%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}" + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } data "azurerm_monitor_action_group" "test" { diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_action_group_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_action_group_test.go index 60db96d6b8b6..d544098eb719 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_action_group_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_action_group_test.go @@ -741,11 +741,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctestFA-%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 - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFA-%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 + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) } @@ -941,11 +942,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctestFA-%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}" - storage_connection_string = "${azurerm_storage_account.test.primary_connection_string}" + name = "acctestFA-%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}" + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/web/resource_arm_function_app.go b/azurerm/internal/services/web/resource_arm_function_app.go index 01f06c4295cc..8819d5b645ec 100644 --- a/azurerm/internal/services/web/resource_arm_function_app.go +++ b/azurerm/internal/services/web/resource_arm_function_app.go @@ -16,6 +16,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/storage" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" @@ -76,11 +77,35 @@ func resourceArmFunctionApp() *schema.Resource { Default: "~1", }, + // TODO remove this in 3.0 "storage_connection_string": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Sensitive: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Sensitive: true, + Deprecated: "Deprecated in favor of `storage_account_name` and `storage_account_access_key`", + ConflictsWith: []string{"storage_account_name", "storage_account_access_key"}, + }, + + "storage_account_name": { + Type: schema.TypeString, + // Required: true, // Uncomment this in 3.0 + Optional: true, + Computed: true, // Remove this in 3.0 + ForceNew: true, + ValidateFunc: storage.ValidateArmStorageAccountName, + ConflictsWith: []string{"storage_connection_string"}, + }, + + "storage_account_access_key": { + Type: schema.TypeString, + Optional: true, + Computed: true, // Remove this in 3.0 + // Required: true, // Uncomment this in 3.0 + Sensitive: true, + ValidateFunc: validation.NoZeroValues, + ConflictsWith: []string{"storage_connection_string"}, }, "app_settings": { @@ -286,6 +311,7 @@ func resourceArmFunctionApp() *schema.Resource { func resourceArmFunctionAppCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Web.AppServicesClient + endpointSuffix := meta.(*clients.Client).Account.Environment.StorageEndpointSuffix ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -340,7 +366,10 @@ func resourceArmFunctionAppCreate(d *schema.ResourceData, meta interface{}) erro return err } - basicAppSettings := getBasicFunctionAppAppSettings(d, appServiceTier) + basicAppSettings, err := getBasicFunctionAppAppSettings(d, appServiceTier, endpointSuffix) + if err != nil { + return err + } siteConfig, err := expandFunctionAppSiteConfig(d) if err != nil { @@ -405,6 +434,7 @@ func resourceArmFunctionAppCreate(d *schema.ResourceData, meta interface{}) erro func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Web.AppServicesClient + endpointSuffix := meta.(*clients.Client).Account.Environment.StorageEndpointSuffix ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -429,11 +459,15 @@ func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) erro t := d.Get("tags").(map[string]interface{}) appServiceTier, err := getFunctionAppServiceTier(ctx, appServicePlanID, meta) + if err != nil { + return err + } + basicAppSettings, err := getBasicFunctionAppAppSettings(d, appServiceTier, endpointSuffix) if err != nil { return err } - basicAppSettings := getBasicFunctionAppAppSettings(d, appServiceTier) + siteConfig, err := expandFunctionAppSiteConfig(d) if err != nil { return fmt.Errorf("Error expanding `site_config` for Function App %q (Resource Group %q): %s", id.Name, id.ResourceGroup, err) @@ -470,7 +504,10 @@ func resourceArmFunctionAppUpdate(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error waiting for update of Function App %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } - appSettings := expandFunctionAppAppSettings(d, appServiceTier) + appSettings, err := expandFunctionAppAppSettings(d, appServiceTier, endpointSuffix) + if err != nil { + return err + } settings := web.StringDictionary{ Properties: appSettings, } @@ -598,7 +635,26 @@ func resourceArmFunctionAppRead(d *schema.ResourceData, meta interface{}) error appSettings := flattenAppServiceAppSettings(appSettingsResp.Properties) - d.Set("storage_connection_string", appSettings["AzureWebJobsStorage"]) + connectionString := appSettings["AzureWebJobsStorage"] + d.Set("storage_connection_string", connectionString) + + // This teases out the necessary attributes from the storage connection string + connectionStringParts := strings.Split(connectionString, ";") + for _, part := range connectionStringParts { + if strings.HasPrefix(part, "AccountName") { + accountNameParts := strings.Split(part, "AccountName=") + if len(accountNameParts) > 1 { + d.Set("storage_account_name", accountNameParts[1]) + } + } + if strings.HasPrefix(part, "AccountKey") { + accountKeyParts := strings.Split(part, "AccountKey=") + if len(accountKeyParts) > 1 { + d.Set("storage_account_access_key", accountKeyParts[1]) + } + } + } + d.Set("version", appSettings["FUNCTIONS_EXTENSION_VERSION"]) dashboard, ok := appSettings["AzureWebJobsDashboard"] @@ -669,7 +725,7 @@ func resourceArmFunctionAppDelete(d *schema.ResourceData, meta interface{}) erro return nil } -func getBasicFunctionAppAppSettings(d *schema.ResourceData, appServiceTier string) []web.NameValuePair { +func getBasicFunctionAppAppSettings(d *schema.ResourceData, appServiceTier, endpointSuffix string) ([]web.NameValuePair, error) { // TODO: This is a workaround since there are no public Functions API // You may track the API request here: https://github.com/Azure/azure-rest-api-specs/issues/3750 dashboardPropName := "AzureWebJobsDashboard" @@ -678,7 +734,34 @@ func getBasicFunctionAppAppSettings(d *schema.ResourceData, appServiceTier strin contentSharePropName := "WEBSITE_CONTENTSHARE" contentFileConnStringPropName := "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" - storageConnection := d.Get("storage_connection_string").(string) + // TODO 3.0 - remove this logic for determining which storage account connection string to use + storageConnection := "" + if v, ok := d.GetOk("storage_connection_string"); ok { + storageConnection = v.(string) + } + + storageAccount := "" + if v, ok := d.GetOk("storage_account_name"); ok { + storageAccount = v.(string) + } + + connectionString := "" + if v, ok := d.GetOk("storage_account_access_key"); ok { + connectionString = v.(string) + } + + if storageConnection == "" && storageAccount == "" && connectionString == "" { + return nil, fmt.Errorf("one of `storage_connection_string` or `storage_account_name` and `storage_account_access_key` must be specified") + } + + if (storageAccount == "" && connectionString != "") || (storageAccount != "" && connectionString == "") { + return nil, fmt.Errorf("both `storage_account_name` and `storage_account_access_key` must be specified") + } + + if connectionString != "" && storageAccount != "" { + storageConnection = fmt.Sprintf("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=%s", storageAccount, connectionString, endpointSuffix) + } + functionVersion := d.Get("version").(string) contentShare := strings.ToLower(d.Get("name").(string)) + "-content" @@ -701,10 +784,10 @@ func getBasicFunctionAppAppSettings(d *schema.ResourceData, appServiceTier strin // On consumption and premium plans include WEBSITE_CONTENT components if strings.EqualFold(appServiceTier, "dynamic") || strings.EqualFold(appServiceTier, "elasticpremium") { - return append(basicSettings, consumptionSettings...) + return append(basicSettings, consumptionSettings...), nil } - return basicSettings + return basicSettings, nil } func getFunctionAppServiceTier(ctx context.Context, appServicePlanId string, meta interface{}) (string, error) { @@ -729,15 +812,18 @@ func getFunctionAppServiceTier(ctx context.Context, appServicePlanId string, met return "", fmt.Errorf("No `sku` block was returned for App Service Plan ID %q", appServicePlanId) } -func expandFunctionAppAppSettings(d *schema.ResourceData, appServiceTier string) map[string]*string { +func expandFunctionAppAppSettings(d *schema.ResourceData, appServiceTier, endpointSuffix string) (map[string]*string, error) { output := expandAppServiceAppSettings(d) - basicAppSettings := getBasicFunctionAppAppSettings(d, appServiceTier) + basicAppSettings, err := getBasicFunctionAppAppSettings(d, appServiceTier, endpointSuffix) + if err != nil { + return nil, err + } for _, p := range basicAppSettings { output[*p.Name] = p.Value } - return output + return output, nil } func expandFunctionAppSiteConfig(d *schema.ResourceData) (web.SiteConfig, error) { diff --git a/azurerm/internal/services/web/tests/resource_arm_function_app_test.go b/azurerm/internal/services/web/tests/resource_arm_function_app_test.go index 205a0af9a642..6e11f49c4a56 100644 --- a/azurerm/internal/services/web/tests/resource_arm_function_app_test.go +++ b/azurerm/internal/services/web/tests/resource_arm_function_app_test.go @@ -3,6 +3,7 @@ package tests import ( "fmt" "os" + "regexp" "strings" "testing" @@ -38,6 +39,60 @@ func TestAccAzureRMFunctionApp_basic(t *testing.T) { }) } +// TODO remove in 3.0 +func TestAccAzureRMFunctionApp_deprecatedConnectionString(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_deprecatedConnectionString(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +// TODO remove in 3.0 +func TestAccAzureRMFunctionApp_deprecatedConnectionStringMissingError(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_deprecatedConnectionStringMissingError(data), + ExpectError: regexp.MustCompile("one of `storage_connection_string` or `storage_account_name` and `storage_account_access_key` must be specified"), + }, + }, + }) +} + +// TODO remove in 3.0 +func TestAccAzureRMFunctionApp_deprecatedNeedBothSAAtrributesError(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_deprecatedConnectionStringBothSpecifiedError(data), + ExpectError: regexp.MustCompile("both `storage_account_name` and `storage_account_access_key` must be specified"), + }, + }, + }) +} + func TestAccAzureRMFunctionApp_requiresImport(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_function_app", "test") resource.ParallelTest(t, resource.TestCase{ @@ -779,6 +834,39 @@ func TestAccAzureRMFunctionApp_manyIpRestrictions(t *testing.T) { }) } +func TestAccAzureRMFunctionApp_updateStorageAccountKey(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_function_app", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMFunctionAppDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMFunctionApp_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMFunctionApp_updateStorageAccountKey(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMFunctionApp_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMFunctionAppExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMFunctionAppDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Web.AppServicesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -930,11 +1018,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomString) } @@ -945,11 +1034,12 @@ func testAccAzureRMFunctionApp_requiresImport(data acceptance.TestData) string { %s resource "azurerm_function_app" "import" { - name = azurerm_function_app.test.name - location = azurerm_function_app.test.location - resource_group_name = azurerm_function_app.test.resource_group_name - app_service_plan_id = azurerm_function_app.test.app_service_plan_id - storage_connection_string = azurerm_function_app.test.storage_connection_string + name = azurerm_function_app.test.name + location = azurerm_function_app.test.location + resource_group_name = azurerm_function_app.test.resource_group_name + app_service_plan_id = azurerm_function_app.test.app_service_plan_id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, template) } @@ -985,11 +1075,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key tags = { environment = "production" @@ -1029,11 +1120,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key tags = { environment = "production" @@ -1074,12 +1166,13 @@ resource "azurerm_app_service_plan" "test" { } 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 - version = "%[4]s" - storage_connection_string = azurerm_storage_account.test.primary_connection_string + 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 + version = "%[4]s" + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomString, version) } @@ -1115,11 +1208,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key app_settings = { "hello" = "world" @@ -1159,11 +1253,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { always_on = true @@ -1206,13 +1301,14 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%[1]d-func" - location = azurerm_resource_group.test.location - version = "~2" - 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 - os_type = "linux" + name = "acctest-%[1]d-func" + location = azurerm_resource_group.test.location + version = "~2" + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + os_type = "linux" site_config { linux_fx_version = "DOCKER|(golang:latest)" @@ -1252,11 +1348,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key connection_string { name = "Example" @@ -1298,11 +1395,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key app_settings = { "hello" = "world" @@ -1349,12 +1447,13 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%[1]d-func" - location = azurerm_resource_group.test.location - version = "~2" - 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 + name = "acctest-%[1]d-func" + location = azurerm_resource_group.test.location + version = "~2" + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key app_settings = { "hello" = "world" @@ -1402,12 +1501,13 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%[1]d-func" - location = azurerm_resource_group.test.location - version = "~2" - 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 + name = "acctest-%[1]d-func" + location = azurerm_resource_group.test.location + version = "~2" + resource_group_name = azurerm_resource_group.test.name + app_service_plan_id = azurerm_app_service_plan.test.id + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key app_settings = { "hello" = "world" @@ -1458,11 +1558,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { use_32_bit_worker_process = false @@ -1502,12 +1603,13 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 - https_only = true + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + https_only = true } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) } @@ -1544,12 +1646,13 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 - daily_memory_time_quota = %d + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + daily_memory_time_quota = %d } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger, dailyMemoryTimeQuota) } @@ -1586,11 +1689,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) } @@ -1627,11 +1731,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%d-FuncWithUppercase" - 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 + name = "acctest-%d-FuncWithUppercase" + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) } @@ -1667,11 +1772,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key identity { type = "SystemAssigned" @@ -1717,11 +1823,12 @@ resource "azurerm_user_assigned_identity" "first" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key identity { type = "UserAssigned" @@ -1774,11 +1881,12 @@ resource "azurerm_user_assigned_identity" "second" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key identity { type = "UserAssigned" @@ -1819,12 +1927,13 @@ resource "azurerm_app_service_plan" "test" { } 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 - enable_builtin_logging = false + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + enable_builtin_logging = false } `, data.RandomInteger, data.Locations.Primary, data.RandomString) } @@ -1860,11 +1969,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key auth_settings { enabled = true @@ -1926,11 +2036,12 @@ resource "azurerm_app_service_plan" "test" { } 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 + 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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { cors { @@ -1979,11 +2090,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { http2_enabled = true @@ -2023,11 +2135,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { min_tls_version = "1.2" @@ -2067,11 +2180,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ftps_state = "AllAllowed" @@ -2156,11 +2270,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -2216,11 +2331,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -2262,11 +2378,12 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%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 + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -2320,15 +2437,176 @@ resource "azurerm_app_service_plan" "test" { } resource "azurerm_function_app" "test" { - name = "acctest-%d-func" + name = "acctest-%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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + + site_config { + ip_restriction = [] + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMFunctionApp_deprecatedConnectionString(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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 +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} - site_config { - ip_restriction = [] +func testAccAzureRMFunctionApp_deprecatedConnectionStringMissingError(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger, data.RandomInteger) + +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 +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + +func testAccAzureRMFunctionApp_deprecatedConnectionStringBothSpecifiedError(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_account_name = azurerm_storage_account.test.name +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + +func testAccAzureRMFunctionApp_updateStorageAccountKey(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +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_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.secondary_access_key +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) } diff --git a/website/docs/r/function_app.html.markdown b/website/docs/r/function_app.html.markdown index 4aee16b7c43e..cb4600689d52 100644 --- a/website/docs/r/function_app.html.markdown +++ b/website/docs/r/function_app.html.markdown @@ -39,11 +39,12 @@ resource "azurerm_app_service_plan" "example" { } resource "azurerm_function_app" "example" { - name = "test-azure-functions" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - app_service_plan_id = azurerm_app_service_plan.example.id - storage_connection_string = azurerm_storage_account.example.primary_connection_string + name = "test-azure-functions" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + app_service_plan_id = azurerm_app_service_plan.example.id + storage_account_name = azurerm_storage_account.test.id + storage_account_access_key = azurerm_storage_account.test.primary_access_key } ``` ## Example Usage (in a Consumption Plan) @@ -75,11 +76,12 @@ resource "azurerm_app_service_plan" "example" { } resource "azurerm_function_app" "example" { - name = "test-azure-functions" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - app_service_plan_id = azurerm_app_service_plan.example.id - storage_connection_string = azurerm_storage_account.example.primary_connection_string + name = "test-azure-functions" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + app_service_plan_id = azurerm_app_service_plan.example.id + storage_account_name = azurerm_storage_account.test.id + storage_account_access_key = azurerm_storage_account.test.primary_access_key } ``` @@ -95,7 +97,9 @@ The following arguments are supported: * `app_service_plan_id` - (Required) The ID of the App Service Plan within which to create this Function App. -* `storage_connection_string` - (Required) The connection string of the backend storage account which will be used by this Function App (such as the dashboard, logs). +* `storage_account_name` - (Required) The backend storage account name which will be used by this Function App (such as the dashboard, logs). + +* `storage_account_access_key` - (Required) The access key which will be used to access the backend storage account for the Function App. * `app_settings` - (Optional) A key-value pair of App Settings.