diff --git a/internal/services/appservice/helpers/function_app_schema.go b/internal/services/appservice/helpers/function_app_schema.go index 8844f5a64dfb..ba4529df96ab 100644 --- a/internal/services/appservice/helpers/function_app_schema.go +++ b/internal/services/appservice/helpers/function_app_schema.go @@ -2,6 +2,7 @@ package helpers import ( "fmt" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "strconv" "strings" @@ -1278,10 +1279,18 @@ func windowsFunctionAppStackSchema() *pluginsdk.Schema { "dotnet_version": { Type: pluginsdk.TypeString, Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - "3.1", - "6", - }, false), + ValidateFunc: func() pluginsdk.SchemaValidateFunc { + if !features.FourPointOh() { + return validation.StringInSlice([]string{ + "3.1", + "core3.1", + "6"}, false) + } + return validation.StringInSlice([]string{ + "core3.1", + "v6.0", + }, false) + }(), ExactlyOneOf: []string{ "site_config.0.application_stack.0.dotnet_version", "site_config.0.application_stack.0.java_version", @@ -1327,7 +1336,7 @@ func windowsFunctionAppStackSchema() *pluginsdk.Schema { Type: pluginsdk.TypeString, Optional: true, ValidateFunc: validation.StringInSlice([]string{ - "8", + "1.8", "11", }, false), ExactlyOneOf: []string{ @@ -1337,7 +1346,7 @@ func windowsFunctionAppStackSchema() *pluginsdk.Schema { "site_config.0.application_stack.0.powershell_core_version", "site_config.0.application_stack.0.use_custom_runtime", }, - Description: "The version of Java to use. Possible values are `8`, and `11`", + Description: "The version of Java to use. Possible values are `1.8`, and `11`", }, "powershell_core_version": { @@ -1803,6 +1812,11 @@ func ExpandSiteConfigWindowsFunctionApp(siteConfig []SiteConfigWindowsFunctionAp appSettings = updateOrAppendAppSettings(appSettings, "FUNCTIONS_WORKER_RUNTIME", "dotnet", false) expanded.WindowsFxVersion = utils.String(fmt.Sprintf("DOTNET|%s", windowsAppStack.DotNetVersion)) } + if windowsAppStack.DotNetVersion == "3.1" || windowsAppStack.DotNetVersion == "core3.1" { + expanded.NetFrameworkVersion = nil + } else { + expanded.NetFrameworkVersion = utils.String(windowsAppStack.DotNetVersion) + } } if windowsAppStack.NodeVersion != "" { @@ -1814,11 +1828,13 @@ func ExpandSiteConfigWindowsFunctionApp(siteConfig []SiteConfigWindowsFunctionAp if windowsAppStack.JavaVersion != "" { appSettings = updateOrAppendAppSettings(appSettings, "FUNCTIONS_WORKER_RUNTIME", "java", false) expanded.WindowsFxVersion = utils.String(fmt.Sprintf("Java|%s", windowsAppStack.JavaVersion)) + expanded.JavaVersion = utils.String(windowsAppStack.JavaVersion) } if windowsAppStack.PowerShellCoreVersion != "" { appSettings = updateOrAppendAppSettings(appSettings, "FUNCTIONS_WORKER_RUNTIME", "powershell", false) expanded.WindowsFxVersion = utils.String(fmt.Sprintf("PowerShell|%s", windowsAppStack.PowerShellCoreVersion)) + expanded.PowerShellVersion = utils.String(windowsAppStack.PowerShellCoreVersion) } if windowsAppStack.CustomHandler { @@ -2007,7 +2023,7 @@ func FlattenSiteConfigLinuxFunctionApp(functionAppSiteConfig *web.SiteConfig) (* return result, nil } -func FlattenSiteConfigWindowsFunctionApp(functionAppSiteConfig *web.SiteConfig) (*SiteConfigWindowsFunctionApp, error) { +func FlattenSiteConfigWindowsFunctionApp(functionAppSiteConfig *web.SiteConfig, isCustomHandler bool, nodeVersion string) (*SiteConfigWindowsFunctionApp, error) { if functionAppSiteConfig == nil { return nil, fmt.Errorf("flattening site config: SiteConfig was nil") } @@ -2071,15 +2087,23 @@ func FlattenSiteConfigWindowsFunctionApp(functionAppSiteConfig *web.SiteConfig) } } - var appStack []ApplicationStackWindowsFunctionApp + var winFunctionAppStack ApplicationStackWindowsFunctionApp + winFunctionAppStack.JavaVersion = utils.NormalizeNilableString(functionAppSiteConfig.JavaVersion) + winFunctionAppStack.PowerShellCoreVersion = utils.NormalizeNilableString(functionAppSiteConfig.PowerShellVersion) + // we need to target the Node versions in app_setting {WEBSITE_NODE_DEFAULT_VERSION} + if nodeVersion != "" { + winFunctionAppStack.NodeVersion = nodeVersion + } if functionAppSiteConfig.WindowsFxVersion != nil { decoded, err := DecodeFunctionAppWindowsFxVersion(*functionAppSiteConfig.WindowsFxVersion) if err != nil { return nil, fmt.Errorf("flattening site config: %s", err) } - appStack = decoded + if len(decoded) > 0 { + winFunctionAppStack = decoded[0] + } } - result.ApplicationStack = appStack + result.ApplicationStack = []ApplicationStackWindowsFunctionApp{winFunctionAppStack} return result, nil } diff --git a/internal/services/appservice/helpers/function_app_slot_schema.go b/internal/services/appservice/helpers/function_app_slot_schema.go index 7c714e60ddd8..8aa2aaeda6fc 100644 --- a/internal/services/appservice/helpers/function_app_slot_schema.go +++ b/internal/services/appservice/helpers/function_app_slot_schema.go @@ -869,7 +869,7 @@ func ExpandSiteConfigWindowsFunctionAppSlot(siteConfig []SiteConfigWindowsFuncti return expanded, nil } -func FlattenSiteConfigWindowsFunctionAppSlot(functionAppSlotSiteConfig *web.SiteConfig) (*SiteConfigWindowsFunctionAppSlot, error) { +func FlattenSiteConfigWindowsFunctionAppSlot(functionAppSlotSiteConfig *web.SiteConfig, isCustomHandler bool, nodeVersion string) (*SiteConfigWindowsFunctionAppSlot, error) { if functionAppSlotSiteConfig == nil { return nil, fmt.Errorf("flattening site config: SiteConfig was nil") } @@ -934,15 +934,24 @@ func FlattenSiteConfigWindowsFunctionAppSlot(functionAppSlotSiteConfig *web.Site } } - var appStack []ApplicationStackWindowsFunctionApp + var winFunctionAppStack ApplicationStackWindowsFunctionApp + winFunctionAppStack.JavaVersion = utils.NormalizeNilableString(functionAppSlotSiteConfig.JavaVersion) + winFunctionAppStack.PowerShellCoreVersion = utils.NormalizeNilableString(functionAppSlotSiteConfig.PowerShellVersion) + + // we need to target the Node versions in app_setting {WEBSITE_NODE_DEFAULT_VERSION} + if nodeVersion != "" { + winFunctionAppStack.NodeVersion = nodeVersion + } if functionAppSlotSiteConfig.WindowsFxVersion != nil { decoded, err := DecodeFunctionAppWindowsFxVersion(*functionAppSlotSiteConfig.WindowsFxVersion) if err != nil { return nil, fmt.Errorf("flattening site config: %s", err) } - appStack = decoded + if len(decoded) > 0 { + winFunctionAppStack = decoded[0] + } } - result.ApplicationStack = appStack + result.ApplicationStack = []ApplicationStackWindowsFunctionApp{winFunctionAppStack} return result, nil } diff --git a/internal/services/appservice/helpers/fx_strings.go b/internal/services/appservice/helpers/fx_strings.go index eae7b2db00e6..4bf6e9edd7fc 100644 --- a/internal/services/appservice/helpers/fx_strings.go +++ b/internal/services/appservice/helpers/fx_strings.go @@ -221,18 +221,6 @@ func DecodeFunctionAppWindowsFxVersion(input string) ([]ApplicationStackWindowsF case "dotnet-isolated": appStack := ApplicationStackWindowsFunctionApp{DotNetVersion: parts[1], DotNetIsolated: true} result = append(result, appStack) - - case "node": - appStack := ApplicationStackWindowsFunctionApp{NodeVersion: parts[1]} - result = append(result, appStack) - - case "java": - appStack := ApplicationStackWindowsFunctionApp{JavaVersion: parts[1]} - result = append(result, appStack) - - case "powershell": - appStack := ApplicationStackWindowsFunctionApp{PowerShellCoreVersion: parts[1]} - result = append(result, appStack) } return result, nil diff --git a/internal/services/appservice/windows_function_app_data_source.go b/internal/services/appservice/windows_function_app_data_source.go index 88eaf7125e64..c3643a145966 100644 --- a/internal/services/appservice/windows_function_app_data_source.go +++ b/internal/services/appservice/windows_function_app_data_source.go @@ -325,15 +325,24 @@ func (d WindowsFunctionAppDataSource) Read() sdk.ResourceFunc { return fmt.Errorf("making Read request on AzureRM Function App Configuration %q: %+v", id.SiteName, err) } - siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionApp(configResp.SiteConfig) + functionApp.unpackWindowsFunctionAppSettings(appSettingsResp) + isCustomHandler := false + nodeVersion := "" + appSetting := functionApp.AppSettings + if appSetting["FUNCTIONS_WORKER_RUNTIME"] == "custom" { + isCustomHandler = true + } + if appSetting["WEBSITE_NODE_DEFAULT_VERSION"] != "" { + nodeVersion = appSetting["WEBSITE_NODE_DEFAULT_VERSION"] + } + + siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionApp(configResp.SiteConfig, isCustomHandler, nodeVersion) if err != nil { return fmt.Errorf("reading Site Config for Windows %s: %+v", id, err) } functionApp.SiteConfig = []helpers.SiteConfigWindowsFunctionApp{*siteConfig} - functionApp.unpackWindowsFunctionAppSettings(appSettingsResp) - functionApp.ConnectionStrings = helpers.FlattenConnectionStrings(connectionStrings) functionApp.SiteCredentials = helpers.FlattenSiteCredentials(siteCredentials) diff --git a/internal/services/appservice/windows_function_app_resource.go b/internal/services/appservice/windows_function_app_resource.go index 246ce171bde1..ebe53f53f4fd 100644 --- a/internal/services/appservice/windows_function_app_resource.go +++ b/internal/services/appservice/windows_function_app_resource.go @@ -617,14 +617,23 @@ func (r WindowsFunctionAppResource) Read() sdk.ResourceFunc { return fmt.Errorf("making Read request on AzureRM Function App Configuration %q: %+v", id.SiteName, err) } - siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionApp(configResp.SiteConfig) + state.unpackWindowsFunctionAppSettings(appSettingsResp, metadata) + isCustomHandler := false + nodeVersion := "" + appSetting := state.AppSettings + if appSetting["FUNCTIONS_WORKER_RUNTIME"] == "custom" { + isCustomHandler = true + } + if appSetting["WEBSITE_NODE_DEFAULT_VERSION"] != "" { + nodeVersion = appSetting["WEBSITE_NODE_DEFAULT_VERSION"] + } + + siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionApp(configResp.SiteConfig, isCustomHandler, nodeVersion) if err != nil { return fmt.Errorf("reading Site Config for Windows %s: %+v", id, err) } state.SiteConfig = []helpers.SiteConfigWindowsFunctionApp{*siteConfig} - state.unpackWindowsFunctionAppSettings(appSettingsResp, metadata) - state.ConnectionStrings = helpers.FlattenConnectionStrings(connectionStrings) state.SiteCredentials = helpers.FlattenSiteCredentials(siteCredentials) @@ -1001,7 +1010,11 @@ func (m *WindowsFunctionAppModel) unpackWindowsFunctionAppSettings(input web.Str case "FUNCTIONS_EXTENSION_VERSION": m.FunctionExtensionsVersion = utils.NormalizeNilableString(v) - case "WEBSITE_NODE_DEFAULT_VERSION": // Note - This is only set if it's not the default of 12, but we collect it from WindowsFxVersion so can discard it here + case "WEBSITE_NODE_DEFAULT_VERSION": + if _, ok := metadata.ResourceData.GetOk("app_settings.WEBSITE_NODE_DEFAULT_VERSION"); ok { + appSettings[k] = utils.NormalizeNilableString(v) + } + case "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": if _, ok := metadata.ResourceData.GetOk("app_settings.WEBSITE_CONTENTAZUREFILECONNECTIONSTRING"); ok { appSettings[k] = utils.NormalizeNilableString(v) diff --git a/internal/services/appservice/windows_function_app_resource_test.go b/internal/services/appservice/windows_function_app_resource_test.go index 5aaccc64cd52..0165f1602d78 100644 --- a/internal/services/appservice/windows_function_app_resource_test.go +++ b/internal/services/appservice/windows_function_app_resource_test.go @@ -792,6 +792,7 @@ func TestAccWindowsFunctionApp_appStackDotNet31(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.dotnet_version").HasValue("3.1"), ), }, data.ImportStep(), @@ -915,6 +916,7 @@ func TestAccWindowsFunctionApp_appStackJava(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.java_version").HasValue("11"), ), }, data.ImportStep(), @@ -927,7 +929,7 @@ func TestAccWindowsFunctionApp_appStackJavaUpdate(t *testing.T) { data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.appStackJava(data, SkuBasicPlan, "8"), + Config: r.appStackJava(data, SkuBasicPlan, "1.8"), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), @@ -955,6 +957,7 @@ func TestAccWindowsFunctionApp_appStackPowerShellCore(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.powershell_core_version").HasValue("7"), ), }, data.ImportStep(), diff --git a/internal/services/appservice/windows_function_app_slot_resource.go b/internal/services/appservice/windows_function_app_slot_resource.go index 3a47b06699e0..65f38c67d637 100644 --- a/internal/services/appservice/windows_function_app_slot_resource.go +++ b/internal/services/appservice/windows_function_app_slot_resource.go @@ -593,14 +593,23 @@ func (r WindowsFunctionAppSlotResource) Read() sdk.ResourceFunc { return fmt.Errorf("making Read request on AzureRM Function App Configuration %q: %+v", id.SiteName, err) } - siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionAppSlot(configResp.SiteConfig) + state.unpackWindowsFunctionAppSettings(appSettingsResp, metadata) + isCustomHandler := false + nodeVersion := "" + appSetting := state.AppSettings + if appSetting["FUNCTIONS_WORKER_RUNTIME"] == "custom" { + isCustomHandler = true + } + if appSetting["WEBSITE_NODE_DEFAULT_VERSION"] != "" { + nodeVersion = appSetting["WEBSITE_NODE_DEFAULT_VERSION"] + } + + siteConfig, err := helpers.FlattenSiteConfigWindowsFunctionAppSlot(configResp.SiteConfig, isCustomHandler, nodeVersion) if err != nil { return fmt.Errorf("reading Site Config for Windows %s: %+v", id, err) } state.SiteConfig = []helpers.SiteConfigWindowsFunctionAppSlot{*siteConfig} - state.unpackWindowsFunctionAppSettings(appSettingsResp, metadata) - state.ConnectionStrings = helpers.FlattenConnectionStrings(connectionStrings) state.SiteCredentials = helpers.FlattenSiteCredentials(siteCredentials) diff --git a/internal/services/appservice/windows_function_app_slot_resource_test.go b/internal/services/appservice/windows_function_app_slot_resource_test.go index a8ba79aa2470..d0e68353526a 100644 --- a/internal/services/appservice/windows_function_app_slot_resource_test.go +++ b/internal/services/appservice/windows_function_app_slot_resource_test.go @@ -580,6 +580,7 @@ func TestAccWindowsFunctionAppSlot_appStackDotNet31(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.dotnet_version").HasValue("3.1"), ), }, data.ImportStep(), @@ -596,6 +597,7 @@ func TestAccWindowsFunctionAppSlot_appStackDotNet6(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.dotnet_version").HasValue("6"), ), }, data.ImportStep(), @@ -668,6 +670,7 @@ func TestAccWindowsFunctionAppSlot_appStackJava(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.java_version").HasValue("11"), ), }, data.ImportStep(), @@ -680,7 +683,7 @@ func TestAccWindowsFunctionAppSlot_appStackJavaUpdate(t *testing.T) { data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.appStackJava(data, SkuStandardPlan, "8"), + Config: r.appStackJava(data, SkuStandardPlan, "1.8"), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), @@ -708,6 +711,7 @@ func TestAccWindowsFunctionAppSlot_appStackPowerShellCore(t *testing.T) { Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("kind").HasValue("functionapp"), + check.That(data.ResourceName).Key("site_config.0.application_stack.0.powershell_core_version").HasValue("7"), ), }, data.ImportStep(), diff --git a/website/docs/r/windows_function_app.html.markdown b/website/docs/r/windows_function_app.html.markdown index 2ad52917d16c..7cd3999ccb77 100644 --- a/website/docs/r/windows_function_app.html.markdown +++ b/website/docs/r/windows_function_app.html.markdown @@ -141,7 +141,7 @@ A `application_stack` block supports the following: * `use_dotnet_isolated_runtime` - (Optional) Should the DotNet process use an isolated runtime. Defaults to `false`. -* `java_version` - (Optional) The Version of Java to use. Supported versions include `8`, and `11`. +* `java_version` - (Optional) The Version of Java to use. Supported versions include `1.8`, and `11`. * `node_version` - (Optional) The version of Node to run. Possible values include `~12`, `~14`, and `~16`.