Terraform-provider-azurerm: azurerm_function_app Example Usage (Linux) in docs produces error on apply

Created on 30 Jul 2020  路  7Comments  路  Source: terraform-providers/terraform-provider-azurerm

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 v0.12.28

  • provider.azurerm v2.20.0

Affected Resource(s)

  • azurerm_function_app
  • azurerm_app_service_plan

Terraform Configuration Files

provider "azurerm" {
  # https://github.com/terraform-providers/terraform-provider-azurerm/releases
  version = "=2.20.0"
  features {}
  subscription_id = var.subscription.internet_test
}

# Copied straight from documentation:
# https://www.terraform.io/docs/providers/azurerm/r/function_app.html#example-usage-linux-

resource "azurerm_resource_group" "example" {
  name     = "azure-functions-cptest-rg"
  location = "westus2"
}

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

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-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
}

Debug Output

Panic Output

Expected Behavior

When copy-pasting example from documentation working infrastructure is expected.

Actual Behavior

Terraform spits out an error when creating azurerm_app_service_plan:

Error: `reserved` has to be set to false when kind isn't set to `Linux`

Steps to Reproduce

  1. terraform apply

Important Factoids

There seem to be some confusion around:

  • Validation logic (error above)
  • Actual Azure behavior
  • Documentation

All in all it is very challenging to produce working configuration for Linux Function, since you get stuck either because of validation or incompatible configuration parameters:

Complete working example for version 2.20.0 in documentation would be helpful or at least documentation could state that Linux Function Apps are not supported in version 2.20.0 due to bugs X and Y.

References

  • #4396
  • #6931
servicapp-service

Most helpful comment

tried this morning with release 2.21.0 and could make it work with kind = "FunctionApp" and reserved = true (and no need to ignore lifecycle changes. These settings actually produce a Linux capable App Service Plan. So for me 2.21.0 fixed this issue, along with #4396.
Can you guys confirm you have the same experience?

All 7 comments

I faced the same issue but i followed terraform documentation and it worked.

you need to set kind to Linux in azurerm_app_service_plan

kind        = "Linux"
reserved =  true

You can refer the examples here - https://www.terraform.io/docs/providers/azurerm/r/app_service_plan.html

@asinitson thanks for point this Issue. This problem has been fixed by #7943, and will be available soon in next version 2.21. Before released, you could try @prabhakarreddy1234 solution for now.

Solution with...

kind        = "Linux"
reserved =  true

...will cause endless resource update loops since azurerm_app_service_plan will be always marked for change. That is why I am rely hesitant to use it (it really messes up workflow).

Update

Okay, found the missing part to the full solution here. So the full solution should be:

resource "azurerm_app_service_plan" "example" {
  name                = "azure-functions-test-service-plan"
  location            = azurerm_resource_group.group.location
  resource_group_name = azurerm_resource_group.group.name
  kind                = "Linux"
  reserved            = true

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

  # Avoid perpetual change cycle due to kind being set to `functionapp`
  # instead of `Linux` when creating the resource in azurerm 2.20.0
  # https://github.com/terraform-providers/terraform-provider-azurerm/issues/7960
  lifecycle {
    ignore_changes = [
      kind
    ]
  }

}

tried this morning with release 2.21.0 and could make it work with kind = "FunctionApp" and reserved = true (and no need to ignore lifecycle changes. These settings actually produce a Linux capable App Service Plan. So for me 2.21.0 fixed this issue, along with #4396.
Can you guys confirm you have the same experience?

After further testing with version 2.21.0 I found out some interesting behavior. _(It was a surprise for me, but I guess it makes some kind of sacred marketing Microsoft sense somewhere.)_ Constantly marking azurerm_app_service_plan for a change behavior depends on size and tier which control compatible and allowed parameters on the Azure side. Azure falls back to allowed values instead of failing loudly (which, in my opinion, would be correct behavior), hence this _enjoyable_ behavior.

I don't think adding additional validation on Terraform side will make things any better (it was already making things worse in version 2.20.0) since Terraform provider will be forced to keep them in sync with whatever is the latest in the Azure.

These are compatible combinations I tested and saw working well (running terraform 2nd time resulted in no changes applied):

    sku  {
        size = "Y1"
        tier = "Dynamic"
    }
    # If you try using "Linux", you will get perpetual pending change,
    # because kind will always be set to `functionapp` (lowercase for some reason)
    kind = "FunctionApp"

    # If you set this to `20` it will fallback to 1 anyway causing perpetual pending change
    maximum_elastic_worker_count = 1
    sku  {
        size = "S1"
        tier = "Standard"
   }

    # If you try using "FunctionApp", you will get perpetual pending change,
    # because kind will always be set to `linux` (lowercase for some reason)
    kind = "Linux"
    reserved = true

    # If you set this to `20` it will fallback to 1 anyway causing perpetual pending change
    maximum_elastic_worker_count = 1

@asinitson you are right that azure backend service will fall back to allowed values, but which could cause fields diff in terraform and lead to annoying message. What's worse, because of the diff, terraform would try to recreate it. This is absolutely not right.

So adding some validation to avoid such config could help a lot of users. They only want to correctly provision those resources without knowing the service backend implementation details.

I am sorry for the inconvinience by the bug in version 2.20, It's a wrong commit that introduced this bug, the validation logic is not right. With proper validation, it could no doubt benefit lots of people.

@njuCZ: The point I was making was that wrong validation is worse than no validation.

The problem with any kind of validation is that it should be based on the same rules and ideally those rules should come from the same source. Terraform validation rules cannot be the primary source of validation and they will probably always be somewhat out of date. By making a favor to the user in some cases you will be still hurting users in other cases. All this leads to the thought that it's better not to have any validation, which at least gives user the choice of providing the right configuration and check things manually.

But maybe I am making a bigger deal out this than it really and it was just one problem and otherwise validation is pretty solid and useful. Don't have much experience with Terraform to say which way it is.

Was this page helpful?
0 / 5 - 0 ratings