Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function app slot (azurerm_function_app_slot) is created with bad value for WEBSITE_CONTENTSHARE app setting #7888

Open
satano opened this issue Jul 24, 2020 · 2 comments

Comments

@satano
Copy link

satano commented Jul 24, 2020

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and AzureRM Provider) Version

  • Terraform: 0.12.29
  • AzureRM provider: 2.20.0

Affected Resource(s)

  • azurerm_function_app_slot

Terraform Configuration Files

provider "azurerm" {
  version = "=2.20.0"
  features {}
}

resource "azurerm_resource_group" "example" {
  name     = "tf-test-contentshare-rsg"
  location = "westeurope"
}

resource "azurerm_storage_account" "example" {
  name                     = "azfuncteststfcontentshare"
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  static_website {
    index_document     = "index.html"
    error_404_document = "error.html"
  }

  blob_properties {
    cors_rule {
      allowed_headers    = ["*"]
      allowed_methods    = ["DELETE", "GET", "POST", "PUT"]
      allowed_origins    = ["*"]
      exposed_headers    = ["*"]
      max_age_in_seconds = 300
    }
  }
}

resource "azurerm_app_service_plan" "example" {
  name                = "azure-functions-test-service-plan"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  kind                = "FunctionApp"

  sku {
    tier = "Dynamic"
    size = "Y1"
  }
}

resource "azurerm_function_app" "example" {
  name                       = "test-azure-function-contentshare"
  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.example.name
  storage_account_access_key = azurerm_storage_account.example.primary_access_key

  site_config {
    http2_enabled = true
  }

  app_settings = {
    "ASPNETCORE_ENVIRONMENT"          = "Production"
    "WEBSITE_NODE_DEFAULT_VERSION"    = "~12"
    "FUNCTIONS_WORKER_RUNTIME"        = "dotnet"
    "WEBSITE_ENABLE_SYNC_UPDATE_SITE" = "true"
    "WEBSITE_RUN_FROM_PACKAGE"        = "1"
  }
}

resource "azurerm_function_app_slot" "example" {
  name                       = "staging"
  location                   = azurerm_resource_group.example.location
  resource_group_name        = azurerm_resource_group.example.name
  app_service_plan_id        = azurerm_app_service_plan.example.id
  function_app_name          = azurerm_function_app.example.name
  storage_account_name       = azurerm_storage_account.example.name
  storage_account_access_key = azurerm_storage_account.example.primary_access_key

  site_config {
    http2_enabled = true
  }

  app_settings = {
    "ASPNETCORE_ENVIRONMENT"          = "Staging"
    "WEBSITE_NODE_DEFAULT_VERSION"    = "~12"
    "FUNCTIONS_WORKER_RUNTIME"        = "dotnet"
    "WEBSITE_ENABLE_SYNC_UPDATE_SITE" = "true"
    "WEBSITE_RUN_FROM_PACKAGE"        = "1"
  }
}

Debug Output

https://gist.github.com/satano/d384cce1d3a7e68302c3e2e3a2678979

Expected Behavior

When the function app slot is created, configuration value WEBSITE_CONTENTSHARE must contain parent function app name and slot name - so in general, it must be unique. I would recommend generating the value as {parent-function-app-name}-{slot-name}. For the terraform config above, the value would be test-azure-function-contentshare-staging.

If WEBSITE_CONTENTSHARE valuse is explicitly set in .tf file, this value should be used.

Note, that when creating a slot in Azure Portal, it generates this value this way, but it even adds some random number at the end. But probably this random number is not needed.

Actual Behavior

For function app slot, the value of WEBSITE_CONTENTSHARE is explicitly set to {slot-name}-content, so for above example the value is staging-content. This is a big problem, because the slot name staging is the same for all our funcion apps. And so all of the function apps' slots have the same value of WEBSITE_CONTENTSHARE = "staging-content". The consequence is, that when we deploy our functions into slots, they overwrite themselves. So at the end, we have the same functions deployed to all of our function apps in the staging slot.

We also tried to set this setting explicitly, so we added this to the app_settings above:

"WEBSITE_CONTENTSHARE"                     = "test-azure-function-contentshare-staging"
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING" = azurerm_storage_account.example.primary_connection_string

But this does not work. The WEBSITE_CONTENTSHARE is still set to staging-content, so our explicit value is ignored. But it is even worse, because now terraform thinks that something has changed, because value in .tf file is different than value in the Azure and it wants to update it. And it will update it again to its own value {slot-name}-content so terraform does see this change forever.

Note: The WEBSITE_CONTENTAZUREFILECONNECTIONSTRING is needed when WEBSITE_CONTENTSHARE is explicitly set. This is not an Azure issue, this is terraform's azure provider issue.

Workaround

The workaroud we found is, that we do not set WEBSITE_CONTENTSHARE in our .tf file (the same as in example configuration file above). Terraform creates it with the wrong value. Than we run script, that will replace this config in the server. We are happy to have correct config in our function app slot and terraform is happy, because it does not track this value and so it does not bother us that something has changed.

Of course, this script must run every time terraform apply runs, because terraform will always rewrite our value with the wrong one. It is a simple Azure CLI command running in PowerShell script:

az functionapp config appsettings set --resource-group $env:resourceGroupName --name $env:functioAppName --slot $env:slotName --settings "WEBSITE_CONTENTSHARE=$env:functioAppName-$env:slotName"

Steps to Reproduce

  1. terraform apply
  2. Look at configuration of function app slot in Azure Portal a check WEBSITE_CONTENTSHARE value.

References

Documentation for azurerm_function_app_slot is wrong. It has two issues:

  1. Slot name in the documentation is test-azure-functions_slot, but this name is invalid. _ (underscore) is invalid character for slot name, so your example fails with error: Error: web.AppsClient#CreateOrUpdateSlot: Failure sending request: StatusCode=400 -- Original Error: Code="BadRequest" Message="Name test-azure-functions_slot.azurewebsites.net is not valid."
  2. Slot name created this way ({function-app-name}-{slot-name}) is not common. I would even say, it does not make sense to have such a slot name, which is different for each application. In general slot names are simple, representing some environment. So for example common slot names are staging, devel, test, feature-x… And the same slot name is used on many web/function apps.
@mybayern1974 mybayern1974 added the service/functions Function Apps label Jul 27, 2020
@lobsteropteryx
Copy link

We're seeing similar issues as well. In addition, we've noticed that terraform will overwrite the WEBSITE_CONTENTSHARE value after swapping, so that both slots end up with the same value. When that happens everything still works, but both slots point to the same version of the app.

@lilpug
Copy link

lilpug commented May 26, 2021

this is still quite an issue and has caused us quite a bit of time to try and figure out why our staging and primary function apps where deploying to the same instance, after reading this issue thread and checking both the staging and primary share values, it became clear this was the same problem.

Is there an eta on this? or at least the ability to allow us to use the "lifecycle -> ignore_changes" hook so we can ignore the value after its built the infrastructure the first time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants