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

Optional Azure FunctionApp settings get overwritten when they don't exist in the TF file #5112

Closed
ghost opened this issue Dec 9, 2019 · 12 comments
Labels

Comments

@ghost
Copy link

ghost commented Dec 9, 2019

This issue was originally opened by @mcalnd70 as hashicorp/terraform#23603. It was migrated here as a result of the provider split. The original body of the issue is below.


Terraform Version

Terraform 0.12.17
Azure provider 0.0.137

Terraform Configuration Files

# Define Resource Group
resource "azurerm_resource_group" "go-1" {
  name     = "__azfaresourcegroup1__"
  location = "__azlocation__"
}
# Define Storage Account
resource "azurerm_storage_account" "go-1" {
  name                     = "__azsaname1__"
  resource_group_name      = azurerm_resource_group.go-1.name
  location                 = azurerm_resource_group.go-1.location
  account_tier             = "__azsatier1__"
  account_replication_type = "__azsasku1__"
  access_tier              = "__azsaaccesstier1__"
  account_kind             = "__azsakind1__"
}
# Define App Service Plan 1
resource "azurerm_app_service_plan" "go-1" {
  name                = "__azappplan1__"
  location            = azurerm_resource_group.go-1.location
  resource_group_name = azurerm_resource_group.go-1.name
  kind                = "__azappplankind1__"
  sku {
    tier = "__azappplantier1__"
    size = "__azappplansize1__"
  }
}
# Define Function App 1
resource "azurerm_function_app" "go-1" {
  name                      = "__azfuncapp1__"
  location                  = azurerm_resource_group.go-1.location
  resource_group_name       = azurerm_resource_group.go-1.name
  app_service_plan_id       = azurerm_app_service_plan.go-1.id
  storage_connection_string = azurerm_storage_account.go-1.primary_connection_string
  version                   = "~2"
  site_config {
    use_32_bit_worker_process = "__azfuncapp32bitworker1__"
    always_on = "true"
  }
}
...

Debug Output

Extract from the first PLAN output, it makes no mention of app_settings to be set

   # azurerm_function_app.go-1 will be created
   + resource "azurerm_function_app" "go-1" {
       + app_service_plan_id            = (known after apply)
       + client_affinity_enabled        = (known after apply)
       + default_hostname               = (known after apply)
       + enable_builtin_logging         = true
       + enabled                        = true
       + https_only                     = false
       + id                             = (known after apply)
       + kind                           = (known after apply)
       + location                       = "westeurope"
       + name                           = "FA-SBX-TEST-BlobIngestion"
       + outbound_ip_addresses          = (known after apply)
       + possible_outbound_ip_addresses = (known after apply)
       + resource_group_name            = "RG-SBX-TEST-FunctionApps"
       + site_credential                = (known after apply)
       + storage_connection_string      = (sensitive value)
       + tags                           = (known after apply)
       + version                        = "~2"
 
       + auth_settings {
           + additional_login_params        = (known after apply)
           + allowed_external_redirect_urls = (known after apply)
           + default_provider               = (known after apply)
           + enabled                        = (known after apply)
           + issuer                         = (known after apply)
           + runtime_version                = (known after apply)
           + token_refresh_extension_hours  = (known after apply)
           + token_store_enabled            = (known after apply)
           + unauthenticated_client_action  = (known after apply)
 
           + active_directory {
               + allowed_audiences = (known after apply)
               + client_id         = (known after apply)
               + client_secret     = (sensitive value)
             }
 
           + facebook {
               + app_id       = (known after apply)
               + app_secret   = (sensitive value)
               + oauth_scopes = (known after apply)
             }
 
           + google {
               + client_id     = (known after apply)
               + client_secret = (sensitive value)
               + oauth_scopes  = (known after apply)
             }
 
           + microsoft {
               + client_id     = (known after apply)
               + client_secret = (sensitive value)
               + oauth_scopes  = (known after apply)
             }
 
           + twitter {
               + consumer_key    = (known after apply)
               + consumer_secret = (sensitive value)
             }
         }
 
       + connection_string {
           + name  = (known after apply)
           + type  = (known after apply)
           + value = (sensitive value)
         }
 
       + identity {
           + principal_id = (known after apply)
           + tenant_id    = (known after apply)
           + type         = (known after apply)
         }
 
       + site_config {
           + always_on                 = true
           + http2_enabled             = false
           + linux_fx_version          = (known after apply)
           + use_32_bit_worker_process = true
           + websockets_enabled        = false
 
           + cors {
               + allowed_origins     = (known after apply)
               + support_credentials = (known after apply)
             }
         }
     }

Crash Output

Expected Behavior

If the app_settings are not specified in the main TF file, then Terraform shouldn't have an opinion on setting them either way (in my view)

The main.tf file does not specify the app_settings, these are indicated by the TF documentation as "optional". Therefore I set them during the actual FunctionApp app code deployment steps outside of Terraform

When the original PLAN runs for Terraform to provision the Function App, it makes no reference in the plan/apply output to anything relating to "app_settings"

Actual Behavior

After the FA code deployment package has been uploaded outside of Terraform, and has set some app_settings, re-running the TF PLAN reports the following app_settings are now going to be "nulled" out, even though (a) they don't exist in the main.tf and (b) the original plan and apply made no mention or had no interest in settings these.

~ app_settings                   = {
- "WEBSITE_ENABLE_SYNC_UPDATE_SITE" = "true" -> null
- "WEBSITE_RUN_FROM_PACKAGE"           = "1" -> null
- "MyApp_Password"            = "1234567abcded" -> null
- "MyApp_Username"           = "testuser" -> null
 }

Steps to Reproduce

  1. Run Terraform against the main.tf file in plan/apply mode - The references prefixed and suffixed by the '__' characters are variables. Name as appropriate. Notice that app_settings is NOT mentioned
  2. Deploy a sample Function App to Azure using Visual Studio or other mechanism. and set some appsettings, either from code or manually in the Azure portal under Function App / Config
  3. Re-run step 1) and you will see the app_settings being nulled

Additional Context

Running in Azure DevOps pipelines, but reproducible via Terraform command line

References

@Altern1ty
Copy link

Hello, is there any progress on this issue? We are running into this exact issue where our pipeline is deploying application settings in our dev environment that regularly change. When we deploy TF it wipes out any deployed application settings.

With an ARM template we can create and maintain a function app without having to include application settings and it preserves the existing ones.

Please add the ability to allow existing application settings to remain.

@mcalnd70
Copy link

mcalnd70 commented Mar 10, 2020

@Altern1ty I gave up on this and found a workaround. Its a pain because I also now have to maintain every Function App with these settings AND a list of variables in my release/deployment pipelines, but hey-ho - these DevOps processes are a massive hackathon anyway!

resource "azurerm_function_app" "go-1" {
name = "azfuncapp1"
location = azurerm_resource_group.go-1.location
resource_group_name = azurerm_resource_group.go-1.name
app_service_plan_id = azurerm_app_service_plan.go-1.id
storage_connection_string = azurerm_storage_account.go-1.primary_connection_string
version = "~2"
app_settings = {
FUNCTIONS_WORKER_RUNTIME = "SetByFACodeReleasePipeline"
DatalakeAccountName = "SetByFACodeReleasePipeline"
EventHubConnectionString = "SetByFACodeReleasePipeline"
WEBSITE_ENABLE_SYNC_UPDATE_SITE = "SetByFACodeReleasePipeline"
WEBSITE_RUN_FROM_PACKAGE = "SetByFACodeReleasePipeline"
}
site_config {
# Note: When using an App Service Plan in the Free or Shared Tiers use_32_bit_worker_process must be set to true.
# https://www.terraform.io/docs/providers/azurerm/r/function_app.html
use_32_bit_worker_process = "true"
always_on = "true"
}
lifecycle {
ignore_changes = [
app_settings["FUNCTIONS_WORKER_RUNTIME"],
app_settings["DatalakeAccountName"],
app_settings["EventHubConnectionString"],
app_settings["WEBSITE_ENABLE_SYNC_UPDATE_SITE"],
app_settings["WEBSITE_RUN_FROM_PACKAGE"]
]
}
}

@drdamour
Copy link
Contributor

personally i prefer that terraform works the way it does, and doesn't ignore settings it sees but doesn't know about. Suppose it did change to what you suggest and just ignores those...now i have a deployment somewhere that presumably does what i want beacuse theres some settings "XYZ" there that tf doesn't know about. I take my TF module/script and apply it to my new environment (like prod)...now i have something that i THINK is the same, but is actually missing "XYZ" setting. That's some implicit magic that i don't want.

I want TF to tell me hey there's this thing out there that you didn't define in your tf...but it's there and it needs to be dealt with. i much prefer the explicit.

I could see this explicit vs implicit concept being configurable per a resource or even a block , but that would take a lot of code to make work. you've found the way to take an explicit block (app_settings) and make parts of it implicit through the lifecycle ignore_hanges

What sucks is that i've seen some tf be implicit and some be explicit and it's not like it's clearly defined anywhere. Somewhere it should say defining one explicit site_config means you must explicitly define all site_config, but in practice a few terraform plans make it pretty clear pretty quick.

@mcalnd70
Copy link

@drdamour "azurerm_function_app" doesn't work in the same manner as "azurerm_app_service" does, and this is the main issue for me, no consistency. "azurerm_app_service" works better and this is also how the "azurerm_function_app" function should work, i.e. don't overwrite app settings if they haven't been explicitly defined by Terraform

@drdamour
Copy link
Contributor

@mcalnd70 pretty sure you are mistaken. If i go in the portal and add a setting then run a tf plan i see that setting i just added that tf file doesnt know about being shown as will be deleted. The behaviour is consistent across the two types

@chdalski
Copy link

I can confirm that bug for Terraform v0.12.28.

@sonic1981
Copy link

I've since found a solution to this issue, you can add an ignore block to the lifecycle to ignore any settings you want terraform not to control.

So simply add:

resource "azurerm_function_app" "go-1" {
....
  lifecycle {
      ignore_changes = [
        app_settings["appsetting you want terraform to ignore"],
      ]
    }
}

@mcalnd70
Copy link

mcalnd70 commented Sep 9, 2020

@sonic1981 see post from 10th March

Its a workaround but not ideal as you have constantly come back to the Terraform if a new parm is created in the FA you are deploying code to. You don't have to do this with WebApps, just FunctionApps

@drdamour
Copy link
Contributor

drdamour commented Oct 8, 2020

i'm wondering if this is "fixed" by #8682

@mcalnd70
Copy link

Hi - by stepping up to Azure provider 2.51.0 this is no longer an issue

@favoretti
Copy link
Collaborator

Since this issue seems to have been addressed in the latest versions of the provider (or a valid workaround was provided) - I'm going to close it. Please open a new updated bug report if this is still relevant. Thank you.

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

8 participants