diff --git a/azurerm/internal/services/web/data_source_function_app.go b/azurerm/internal/services/web/data_source_function_app.go index bf4eb6e7a738..1c75bdd9dc6d 100644 --- a/azurerm/internal/services/web/data_source_function_app.go +++ b/azurerm/internal/services/web/data_source_function_app.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + webValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/web/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -25,7 +26,7 @@ func dataSourceArmFunctionApp() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validateAppServiceName, + ValidateFunc: webValidate.AppServiceName, }, "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), diff --git a/azurerm/internal/services/web/function_app_slot.go b/azurerm/internal/services/web/parse/function_app_slot.go similarity index 89% rename from azurerm/internal/services/web/function_app_slot.go rename to azurerm/internal/services/web/parse/function_app_slot.go index c045bba18b1e..5672365f70a8 100644 --- a/azurerm/internal/services/web/function_app_slot.go +++ b/azurerm/internal/services/web/parse/function_app_slot.go @@ -1,4 +1,4 @@ -package web +package parse import ( "fmt" @@ -12,7 +12,7 @@ type FunctionAppSlotResourceID struct { Name string } -func ParseFunctionAppSlotID(input string) (*FunctionAppSlotResourceID, error) { +func FunctionAppSlotID(input string) (*FunctionAppSlotResourceID, error) { id, err := azure.ParseAzureResourceID(input) if err != nil { return nil, fmt.Errorf("[ERROR] Unable to parse App Service Slot ID %q: %+v", input, err) diff --git a/azurerm/internal/services/web/resource_arm_app_service.go b/azurerm/internal/services/web/resource_arm_app_service.go index ba625f76bc47..6cc4c00455c3 100644 --- a/azurerm/internal/services/web/resource_arm_app_service.go +++ b/azurerm/internal/services/web/resource_arm_app_service.go @@ -3,7 +3,6 @@ package web import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/web/mgmt/2019-08-01/web" @@ -14,6 +13,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "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/web/validate" "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" @@ -44,7 +44,7 @@ func resourceArmAppService() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validateAppServiceName, + ValidateFunc: validate.AppServiceName, }, "identity": azure.SchemaAppServiceIdentity(), @@ -760,16 +760,6 @@ func flattenAppServiceAppSettings(input map[string]*string) map[string]string { return output } -func validateAppServiceName(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - - if matched := regexp.MustCompile(`^[0-9a-zA-Z-]{1,60}$`).Match([]byte(value)); !matched { - errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters and dashes and up to 60 characters in length", k)) - } - - return warnings, errors -} - func flattenAppServiceSiteCredential(input *web.UserProperties) []interface{} { results := make([]interface{}, 0) result := make(map[string]interface{}) diff --git a/azurerm/internal/services/web/resource_arm_app_service_slot.go b/azurerm/internal/services/web/resource_arm_app_service_slot.go index e134aa8b1ab1..abf2a96daf91 100644 --- a/azurerm/internal/services/web/resource_arm_app_service_slot.go +++ b/azurerm/internal/services/web/resource_arm_app_service_slot.go @@ -13,6 +13,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + webValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/web/validate" "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" @@ -42,7 +43,7 @@ func resourceArmAppServiceSlot() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validateAppServiceName, + ValidateFunc: webValidate.AppServiceName, }, "resource_group_name": azure.SchemaResourceGroupName(), diff --git a/azurerm/internal/services/web/resource_arm_function_app.go b/azurerm/internal/services/web/resource_arm_function_app.go index fccdac4a91ba..47870acde88c 100644 --- a/azurerm/internal/services/web/resource_arm_function_app.go +++ b/azurerm/internal/services/web/resource_arm_function_app.go @@ -17,6 +17,7 @@ import ( "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" + webValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/web/validate" "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" @@ -48,7 +49,7 @@ func resourceArmFunctionApp() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validateAppServiceName, + ValidateFunc: webValidate.AppServiceName, }, "resource_group_name": azure.SchemaResourceGroupName(), diff --git a/azurerm/internal/services/web/resource_arm_function_app_slot.go b/azurerm/internal/services/web/resource_arm_function_app_slot.go index 7bbf47e2b3d8..2fbec1ca8ec1 100644 --- a/azurerm/internal/services/web/resource_arm_function_app_slot.go +++ b/azurerm/internal/services/web/resource_arm_function_app_slot.go @@ -14,7 +14,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "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/services/web/parse" + webValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/web/validate" "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" @@ -28,7 +30,7 @@ func resourceArmFunctionAppSlot() *schema.Resource { Update: resourceArmFunctionAppSlotUpdate, Delete: resourceArmFunctionAppSlotDelete, Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { - _, err := ParseFunctionAppSlotID(id) + _, err := parse.FunctionAppSlotID(id) return err }), @@ -53,20 +55,17 @@ func resourceArmFunctionAppSlot() *schema.Resource { "identity": azure.SchemaAppServiceIdentity(), "function_app_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "kind": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: webValidate.AppServiceName, }, "app_service_plan_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: ValidateAppServicePlanID, }, "version": { @@ -75,11 +74,18 @@ func resourceArmFunctionAppSlot() *schema.Resource { Default: "~1", }, - "storage_connection_string": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Sensitive: true, + "storage_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: storage.ValidateArmStorageAccountName, + }, + + "storage_account_access_key": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.NoZeroValues, }, "app_settings": { @@ -90,16 +96,27 @@ func resourceArmFunctionAppSlot() *schema.Resource { }, }, + "daily_memory_time_quota": { + Type: schema.TypeInt, + Optional: true, + }, + + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "enable_builtin_logging": { Type: schema.TypeBool, Optional: true, Default: true, }, - "client_affinity_enabled": { + "https_only": { Type: schema.TypeBool, Optional: true, - Computed: true, + Default: false, }, "os_type": { @@ -111,21 +128,10 @@ func resourceArmFunctionAppSlot() *schema.Resource { }, false), }, - "https_only": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - - "enabled": { + "client_affinity_enabled": { Type: schema.TypeBool, Optional: true, - Default: true, - }, - - "daily_memory_time_quota": { - Type: schema.TypeInt, - Optional: true, + Computed: true, }, "connection_string": { @@ -170,6 +176,11 @@ func resourceArmFunctionAppSlot() *schema.Resource { Computed: true, }, + "kind": { + Type: schema.TypeString, + Computed: true, + }, + "outbound_ip_addresses": { Type: schema.TypeString, Computed: true, @@ -284,14 +295,17 @@ func resourceArmFunctionAppSlot() *schema.Resource { func resourceArmFunctionAppSlotCreate(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() + log.Printf("[INFO] preparing arguments for AzureRM Function App Slot creation.") + slot := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) functionAppName := d.Get("function_app_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if d.IsNewResource() { existing, err := client.GetSlot(ctx, resourceGroup, functionAppName, slot) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -313,18 +327,22 @@ func resourceArmFunctionAppSlotCreate(d *schema.ResourceData, meta interface{}) } } - appServicePlanId := d.Get("app_service_plan_id").(string) + 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) dailyMemoryTimeQuota := d.Get("daily_memory_time_quota").(int) t := d.Get("tags").(map[string]interface{}) - appServiceTier, err := getFunctionAppServiceTier(ctx, appServicePlanId, meta) + appServiceTier, err := getFunctionAppServiceTier(ctx, appServicePlanID, meta) + if err != nil { + return err + } + + basicAppSettings, err := getBasicFunctionAppSlotAppSettings(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 Slot %q (Resource Group %q): %s", slot, resourceGroup, err) @@ -337,7 +355,7 @@ func resourceArmFunctionAppSlotCreate(d *schema.ResourceData, meta interface{}) Location: &location, Tags: tags.Expand(t), SiteProperties: &web.SiteProperties{ - ServerFarmID: utils.String(appServicePlanId), + ServerFarmID: utils.String(appServicePlanID), Enabled: utils.Bool(enabled), ClientAffinityEnabled: utils.Bool(clientAffinityEnabled), HTTPSOnly: utils.Bool(httpsOnly), @@ -354,19 +372,18 @@ func resourceArmFunctionAppSlotCreate(d *schema.ResourceData, meta interface{}) createFuture, err := client.CreateOrUpdateSlot(ctx, resourceGroup, functionAppName, siteEnvelope, slot) if err != nil { - return fmt.Errorf("Error creating Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err) + return err } err = createFuture.WaitForCompletionRef(ctx, client.Client) if err != nil { - return fmt.Errorf("Error waiting for creation of Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err) + return err } read, err := client.GetSlot(ctx, resourceGroup, functionAppName, slot) if err != nil { - return fmt.Errorf("Error retrieving Slot %q (Function App %q / Resource Group %q): %s", slot, functionAppName, resourceGroup, err) + return err } - if read.ID == nil { return fmt.Errorf("Cannot read ID for Slot %q (Function App %q / Resource Group %q) ID", slot, functionAppName, resourceGroup) } @@ -389,10 +406,11 @@ func resourceArmFunctionAppSlotCreate(d *schema.ResourceData, meta interface{}) func resourceArmFunctionAppSlotUpdate(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() - id, err := ParseFunctionAppSlotID(d.Id()) + id, err := parse.FunctionAppSlotID(d.Id()) if err != nil { return err } @@ -405,19 +423,23 @@ func resourceArmFunctionAppSlotUpdate(d *schema.ResourceData, meta interface{}) kind = "functionapp,linux" } } - appServicePlanId := d.Get("app_service_plan_id").(string) + 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) dailyMemoryTimeQuota := d.Get("daily_memory_time_quota").(int) t := d.Get("tags").(map[string]interface{}) - appServiceTier, err := getFunctionAppServiceTier(ctx, appServicePlanId, meta) + appServiceTier, err := getFunctionAppServiceTier(ctx, appServicePlanID, meta) + if err != nil { + return err + } + basicAppSettings, err := getBasicFunctionAppSlotAppSettings(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 Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err) @@ -430,7 +452,7 @@ func resourceArmFunctionAppSlotUpdate(d *schema.ResourceData, meta interface{}) Location: &location, Tags: tags.Expand(t), SiteProperties: &web.SiteProperties{ - ServerFarmID: utils.String(appServicePlanId), + ServerFarmID: utils.String(appServicePlanID), Enabled: utils.Bool(enabled), ClientAffinityEnabled: utils.Bool(clientAffinityEnabled), HTTPSOnly: utils.Bool(httpsOnly), @@ -455,7 +477,10 @@ func resourceArmFunctionAppSlotUpdate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error waiting for update of Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err) } - appSettings := expandFunctionAppAppSettings(d, appServiceTier) + appSettings, err := expandFunctionAppAppSettings(d, appServiceTier, endpointSuffix) + if err != nil { + return err + } settings := web.StringDictionary{ Properties: appSettings, } @@ -510,7 +535,7 @@ func resourceArmFunctionAppSlotRead(d *schema.ResourceData, meta interface{}) er ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := ParseFunctionAppSlotID(d.Id()) + id, err := parse.FunctionAppSlotID(d.Id()) if err != nil { return err } @@ -518,27 +543,26 @@ func resourceArmFunctionAppSlotRead(d *schema.ResourceData, meta interface{}) er resp, err := client.GetSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Slot %q (Function App %q / Resource Group %q) were not found - removing from state!", id.Name, id.FunctionAppName, id.ResourceGroup) + log.Printf("[DEBUG] Function App Slot %q (Function App %q / Resource Group %q) was not found - removing from state", id.Name, id.FunctionAppName, id.ResourceGroup) d.SetId("") return nil } - - return fmt.Errorf("Error reading Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return fmt.Errorf("Error makeing read request on AzureRM Function App Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err) } appSettingsResp, err := client.ListApplicationSettingsSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name) if err != nil { if utils.ResponseWasNotFound(appSettingsResp.Response) { - log.Printf("[DEBUG] Application Settings of Slot %q (Function App %q / Resource Group %q) were not found", id.Name, id.FunctionAppName, id.ResourceGroup) + log.Printf("[DEBUG] Application Settings of AzureRM Function App Slot %q (Function App %q / Resource Group %q) were not found", id.Name, id.FunctionAppName, id.ResourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Slot %q (Function App %q / Resource Group %q) AppSettings: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return fmt.Errorf("Error making Read request on AzureRM Function App Slot %q (Function App %q / Resource Group %q) AppSettings: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) } connectionStringsResp, err := client.ListConnectionStringsSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name) if err != nil { - return fmt.Errorf("Error making Read request on Slot %q (Function App %q / Resource Group %q) ConnectionStrings: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return fmt.Errorf("Error making Read request on AzureRM Function App Slot %q (Function App %q / Resource Group %q) ConnectionStrings: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) } siteCredFuture, err := client.ListPublishingCredentialsSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name) @@ -551,11 +575,11 @@ func resourceArmFunctionAppSlotRead(d *schema.ResourceData, meta interface{}) er } siteCredResp, err := siteCredFuture.Result(*client) if err != nil { - return fmt.Errorf("Error making Read request on Slot %q (Function App %q / Resource Group %q) Site Credentials: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return fmt.Errorf("Error making Read request on AzureRM Function App Slot %q (Function App %q / Resource Group %q) Site Credentials: %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) } authResp, err := client.GetAuthSettingsSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name) if err != nil { - return fmt.Errorf("Error retrieving the AuthSettings for Slot %q (Function App %q / Resource Group %q): %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return fmt.Errorf("Error retrieving the AuthSettings for AzureRM Function App Slot %q (Function App %q / Resource Group %q): %+v", id.Name, id.FunctionAppName, id.ResourceGroup, err) } d.Set("name", id.Name) @@ -585,7 +609,25 @@ func resourceArmFunctionAppSlotRead(d *schema.ResourceData, meta interface{}) er appSettings := flattenAppServiceAppSettings(appSettingsResp.Properties) - d.Set("storage_connection_string", appSettings["AzureWebJobsStorage"]) + connectionString := appSettings["AzureWebJobsStorage"] + + // 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"] @@ -637,21 +679,74 @@ func resourceArmFunctionAppSlotDelete(d *schema.ResourceData, meta interface{}) ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := ParseFunctionAppSlotID(d.Id()) + id, err := parse.FunctionAppSlotID(d.Id()) if err != nil { return err } - log.Printf("[DEBUG] Deleting Slot %q (Function App %q / Resource Group %q)", id.Name, id.FunctionAppName, id.ResourceGroup) + log.Printf("[DEBUG] Deleting Function App Slot %q (Function App %q / Resource Group %q)", id.Name, id.FunctionAppName, id.ResourceGroup) deleteMetrics := true deleteEmptyServerFarm := false resp, err := client.DeleteSlot(ctx, id.ResourceGroup, id.FunctionAppName, id.Name, &deleteMetrics, &deleteEmptyServerFarm) if err != nil { if !utils.ResponseWasNotFound(resp) { - return fmt.Errorf("Error deleting Slot %q (Function App %q / Resource Group %q): %s", id.Name, id.FunctionAppName, id.ResourceGroup, err) + return err } } return nil } + +func getBasicFunctionAppSlotAppSettings(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" + storagePropName := "AzureWebJobsStorage" + functionVersionPropName := "FUNCTIONS_EXTENSION_VERSION" + contentSharePropName := "WEBSITE_CONTENTSHARE" + contentFileConnStringPropName := "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" + + 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 storageAccount == "" && connectionString == "" { + return nil, fmt.Errorf("both `storage_account_name` and `storage_account_access_key` must be specified") + } + + 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" + + basicSettings := []web.NameValuePair{ + {Name: &storagePropName, Value: &storageConnection}, + {Name: &functionVersionPropName, Value: &functionVersion}, + } + + if d.Get("enable_builtin_logging").(bool) { + basicSettings = append(basicSettings, web.NameValuePair{ + Name: &dashboardPropName, + Value: &storageConnection, + }) + } + + consumptionSettings := []web.NameValuePair{ + {Name: &contentSharePropName, Value: &contentShare}, + {Name: &contentFileConnStringPropName, Value: &storageConnection}, + } + + // On consumption and premium plans include WEBSITE_CONTENT components + if strings.EqualFold(appServiceTier, "dynamic") || strings.EqualFold(appServiceTier, "elasticpremium") { + return append(basicSettings, consumptionSettings...), nil + } + + return basicSettings, nil +} diff --git a/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go b/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go index e0394bb7636b..d09617445c33 100644 --- a/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go +++ b/azurerm/internal/services/web/tests/resource_arm_function_app_slot_test.go @@ -151,6 +151,7 @@ func TestAccAzureRMFunctionAppSlot_clientAffinityEnabledUpdate(t *testing.T) { resource.TestCheckResourceAttr(data.ResourceName, "client_affinity_enabled", "true"), ), }, + data.ImportStep(), { Config: testAccAzureRMFunctionAppSlot_clientAffinityEnabled(data, false), Check: resource.ComposeTestCheckFunc( @@ -182,6 +183,7 @@ func TestAccAzureRMFunctionAppSlot_connectionStrings(t *testing.T) { resource.TestCheckResourceAttr(data.ResourceName, "connection_string.2442860602.type", "PostgreSQL"), ), }, + data.ImportStep(), { Config: testAccAzureRMFunctionAppSlot_connectionStringsUpdated(data), Check: resource.ComposeTestCheckFunc( @@ -714,20 +716,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + 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) } @@ -738,12 +742,13 @@ func testAccAzureRMFunctionAppSlot_requiresImport(data acceptance.TestData) stri %s resource "azurerm_function_app_slot" "import" { - name = azurerm_function_app_slot.test.name - location = azurerm_function_app_slot.test.location - resource_group_name = azurerm_function_app_slot.test.resource_group_name - app_service_plan_id = azurerm_function_app_slot.test.app_service_plan_id - function_app_name = azurerm_function_app_slot.test.function_app_name - storage_connection_string = azurerm_function_app_slot.test.storage_connection_string + name = azurerm_function_app_slot.test.name + location = azurerm_function_app_slot.test.location + resource_group_name = azurerm_function_app_slot.test.resource_group_name + app_service_plan_id = azurerm_function_app_slot.test.app_service_plan_id + function_app_name = azurerm_function_app_slot.test.function_app_name + storage_account_name = azurerm_function_app_slot.test.name + storage_account_access_key = azurerm_function_app_slot.test.primary_access_key } `, template) } @@ -779,20 +784,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + 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 = true @@ -832,20 +839,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { always_on = true @@ -885,20 +894,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key app_settings = { "foo" = "bar" @@ -938,21 +949,23 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string - client_affinity_enabled = %t + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + client_affinity_enabled = %t } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, clientAffinityEnabled) } @@ -988,20 +1001,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key connection_string { name = "First" @@ -1049,20 +1064,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key connection_string { name = "Second" @@ -1110,20 +1127,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { cors { @@ -1170,20 +1189,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key auth_settings { enabled = true @@ -1245,21 +1266,23 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string - enabled = %t + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + enabled = %t } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, enabled) } @@ -1295,21 +1318,23 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string - https_only = %t + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + https_only = %t } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, httpsOnly) } @@ -1345,20 +1370,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { http2_enabled = true @@ -1398,20 +1425,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -1467,20 +1496,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -1522,20 +1553,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction = [] @@ -1575,20 +1608,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { ip_restriction { @@ -1642,20 +1677,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key tags = { Hello = "World" @@ -1695,20 +1732,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key tags = { "Hello" = "World" @@ -1749,20 +1788,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { websockets_enabled = true @@ -1802,20 +1843,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key identity { type = "SystemAssigned" @@ -1855,21 +1898,23 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string - version = "%s" + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key + version = "%s" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger, version) } @@ -1911,20 +1956,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key identity { type = "UserAssigned" @@ -1965,20 +2012,22 @@ resource "azurerm_storage_account" "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 } resource "azurerm_function_app_slot" "test" { - name = "acctestFASlot-%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 - function_app_name = azurerm_function_app.test.name - storage_connection_string = azurerm_storage_account.test.primary_connection_string + name = "acctestFASlot-%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 + function_app_name = azurerm_function_app.test.name + storage_account_name = azurerm_storage_account.test.name + storage_account_access_key = azurerm_storage_account.test.primary_access_key site_config { min_tls_version = "%s" diff --git a/azurerm/internal/services/web/validate/app_service.go b/azurerm/internal/services/web/validate/app_service.go new file mode 100644 index 000000000000..71b389e716ae --- /dev/null +++ b/azurerm/internal/services/web/validate/app_service.go @@ -0,0 +1,16 @@ +package validate + +import ( + "fmt" + "regexp" +) + +func AppServiceName(v interface{}, k string) (warnings []string, errors []error) { + value := v.(string) + + if matched := regexp.MustCompile(`^[0-9a-zA-Z-]{1,60}$`).Match([]byte(value)); !matched { + errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters and dashes and up to 60 characters in length", k)) + } + + return warnings, errors +} diff --git a/azurerm/internal/services/web/validation_test.go b/azurerm/internal/services/web/validation_test.go index 212ac37d14ae..2c185af0baac 100644 --- a/azurerm/internal/services/web/validation_test.go +++ b/azurerm/internal/services/web/validation_test.go @@ -1,6 +1,10 @@ package web -import "testing" +import ( + "testing" + + webValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/web/validate" +) func TestAzureRMAppServicePlanName_validation(t *testing.T) { cases := []struct { @@ -74,7 +78,7 @@ func TestAzureRMAppServiceName_validation(t *testing.T) { } for _, tc := range cases { - _, errors := validateAppServiceName(tc.Value, "azurerm_app_service") + _, errors := webValidate.AppServiceName(tc.Value, "azurerm_app_service") if len(errors) != tc.ErrCount { t.Fatalf("Expected the App Service Name to trigger a validation error for '%s'", tc.Value) diff --git a/website/docs/r/function_app_slot.html.markdown b/website/docs/r/function_app_slot.html.markdown index d9ae3e2673f0..ad5011716f4d 100644 --- a/website/docs/r/function_app_slot.html.markdown +++ b/website/docs/r/function_app_slot.html.markdown @@ -76,11 +76,11 @@ The following arguments are supported: ~> **Note:** When using an App Service Plan in the `Free` or `Shared` Tiers `use_32_bit_worker_process` must be set to `true`. -* `auth_settings` - (Optional) A `auth_settings` block as defined below. +* `auth_settings` - (Optional) An `auth_settings` block as defined below. * `enable_builtin_logging` - (Optional) Should the built-in logging of this Function App be enabled? Defaults to `true`. -* `connection_string` - (Optional) An `connection_string` block as defined below. +* `connection_string` - (Optional) A `connection_string` block as defined below. * `os_type` - (Optional) A string indicating the Operating System type for this function app. @@ -158,7 +158,7 @@ An `auth_settings` block supports the following: * `enabled` - (Required) Is Authentication enabled? -* `active_directory` - (Optional) A `active_directory` block as defined below. +* `active_directory` - (Optional) An `active_directory` block as defined below. * `additional_login_params` - (Optional) Login parameters to send to the OpenID Connect authorization endpoint when a user logs in. Each parameter must be in the form "key=value".