From 9b4c519f61caa62ebf768b8677801e2751de9bd7 Mon Sep 17 00:00:00 2001 From: Elena Xin <39109137+sinbai@users.noreply.github.com> Date: Thu, 23 Nov 2023 00:13:16 +0800 Subject: [PATCH] `azurerm_windows_web_app` : fix the issue of incorrect application stack setting after updating the web app without changing the `application_stack` configuration (#23372) Co-authored-by: jackofallops --- .../helpers/windows_web_app_schema.go | 70 ++++++++++++------- .../appservice/windows_web_app_resource.go | 7 ++ .../windows_web_app_resource_test.go | 48 +++++++++++-- website/docs/r/windows_web_app.html.markdown | 2 + 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/internal/services/appservice/helpers/windows_web_app_schema.go b/internal/services/appservice/helpers/windows_web_app_schema.go index 49ff73111079..47aeee577ba9 100644 --- a/internal/services/appservice/helpers/windows_web_app_schema.go +++ b/internal/services/appservice/helpers/windows_web_app_schema.go @@ -617,34 +617,46 @@ func (s *SiteConfigWindows) ExpandForUpdate(metadata sdk.ResourceMetaData, exist if metadata.ResourceData.HasChange("site_config.0.application_stack") { if len(s.ApplicationStack) == 1 { winAppStack := s.ApplicationStack[0] - if winAppStack.NetFrameworkVersion != "" { - expanded.NetFrameworkVersion = pointer.To(winAppStack.NetFrameworkVersion) - } - if winAppStack.NetCoreVersion != "" { - expanded.NetFrameworkVersion = pointer.To(winAppStack.NetCoreVersion) + if metadata.ResourceData.HasChanges("site_config.0.application_stack.0.dotnet_version", "site_config.0.application_stack.0.dotnet_core_version") { + switch { + case winAppStack.NetFrameworkVersion != "": + expanded.NetFrameworkVersion = pointer.To(winAppStack.NetFrameworkVersion) + case winAppStack.NetCoreVersion != "": + expanded.NetFrameworkVersion = pointer.To(winAppStack.NetCoreVersion) + default: + expanded.NetFrameworkVersion = nil + } } - if winAppStack.PhpVersion != "" { - if winAppStack.PhpVersion != PhpVersionOff { - expanded.PhpVersion = pointer.To(winAppStack.PhpVersion) - } else { - expanded.PhpVersion = pointer.To("") + if metadata.ResourceData.HasChange("site_config.0.application_stack.0.php_version") { + if winAppStack.PhpVersion != "" { + if winAppStack.PhpVersion != PhpVersionOff { + expanded.PhpVersion = pointer.To(winAppStack.PhpVersion) + } else { + expanded.PhpVersion = pointer.To("") + } } } if winAppStack.PythonVersion != "" || winAppStack.Python { expanded.PythonVersion = pointer.To(winAppStack.PythonVersion) } - if winAppStack.JavaVersion != "" { - expanded.JavaVersion = pointer.To(winAppStack.JavaVersion) - switch { - case winAppStack.JavaEmbeddedServer: - expanded.JavaContainer = pointer.To(JavaContainerEmbeddedServer) - expanded.JavaContainerVersion = pointer.To(JavaContainerEmbeddedServerVersion) - case winAppStack.TomcatVersion != "": - expanded.JavaContainer = pointer.To(JavaContainerTomcat) - expanded.JavaContainerVersion = pointer.To(winAppStack.TomcatVersion) - case winAppStack.JavaContainer != "": - expanded.JavaContainer = pointer.To(winAppStack.JavaContainer) - expanded.JavaContainerVersion = pointer.To(winAppStack.JavaContainerVersion) + if metadata.ResourceData.HasChange("site_config.0.application_stack.0.java_version") { + if winAppStack.JavaVersion != "" { + expanded.JavaVersion = pointer.To(winAppStack.JavaVersion) + switch { + case winAppStack.JavaEmbeddedServer: + expanded.JavaContainer = pointer.To(JavaContainerEmbeddedServer) + expanded.JavaContainerVersion = pointer.To(JavaContainerEmbeddedServerVersion) + case winAppStack.TomcatVersion != "": + expanded.JavaContainer = pointer.To(JavaContainerTomcat) + expanded.JavaContainerVersion = pointer.To(winAppStack.TomcatVersion) + case winAppStack.JavaContainer != "": + expanded.JavaContainer = pointer.To(winAppStack.JavaContainer) + expanded.JavaContainerVersion = pointer.To(winAppStack.JavaContainerVersion) + } + } else { + expanded.JavaVersion = nil + expanded.JavaContainer = nil + expanded.JavaContainerVersion = nil } } if !features.FourPointOhBeta() { @@ -807,22 +819,28 @@ func (s *SiteConfigWindows) Flatten(appSiteConfig *web.SiteConfig, currentStack var winAppStack ApplicationStackWindows if currentStack == CurrentStackDotNetCore { winAppStack.NetCoreVersion = pointer.From(appSiteConfig.NetFrameworkVersion) - } - if currentStack == CurrentStackDotNet { + } else { winAppStack.NetFrameworkVersion = pointer.From(appSiteConfig.NetFrameworkVersion) } + winAppStack.PhpVersion = pointer.From(appSiteConfig.PhpVersion) if winAppStack.PhpVersion == "" { winAppStack.PhpVersion = PhpVersionOff } winAppStack.PythonVersion = pointer.From(appSiteConfig.PythonVersion) // This _should_ always be `""` winAppStack.Python = currentStack == CurrentStackPython - winAppStack.JavaVersion = pointer.From(appSiteConfig.JavaVersion) + + // we should only set JavaVersion when currentStack is java since the API will return the value of JavaVersion that was once set + if currentStack == "java" { + winAppStack.JavaVersion = pointer.From(appSiteConfig.JavaVersion) + } switch pointer.From(appSiteConfig.JavaContainer) { case JavaContainerTomcat: - winAppStack.TomcatVersion = *appSiteConfig.JavaContainerVersion + winAppStack.TomcatVersion = pointer.From(appSiteConfig.JavaContainerVersion) + winAppStack.JavaVersion = pointer.From(appSiteConfig.JavaVersion) case JavaContainerEmbeddedServer: winAppStack.JavaEmbeddedServer = true + winAppStack.JavaVersion = pointer.From(appSiteConfig.JavaVersion) } s.WindowsFxVersion = pointer.From(appSiteConfig.WindowsFxVersion) diff --git a/internal/services/appservice/windows_web_app_resource.go b/internal/services/appservice/windows_web_app_resource.go index e66b8d6ba4f6..ec45ee73cc30 100644 --- a/internal/services/appservice/windows_web_app_resource.go +++ b/internal/services/appservice/windows_web_app_resource.go @@ -788,6 +788,13 @@ func (r WindowsWebAppResource) Update() sdk.ResourceFunc { return fmt.Errorf("reading Windows %s: %v", id, err) } + // Despite being part of the defined `Get` response model, site_config is always nil so we get it explicitly + webAppSiteConfig, err := client.GetConfiguration(ctx, id.ResourceGroup, id.SiteName) + if err != nil { + return fmt.Errorf("reading Site Config for Windows %s: %+v", id, err) + } + existing.SiteConfig = webAppSiteConfig.SiteConfig + var serviceFarmId string servicePlanChange := false if existing.SiteProperties.ServerFarmID != nil { diff --git a/internal/services/appservice/windows_web_app_resource_test.go b/internal/services/appservice/windows_web_app_resource_test.go index f5bc76de64e9..5f715d62a497 100644 --- a/internal/services/appservice/windows_web_app_resource_test.go +++ b/internal/services/appservice/windows_web_app_resource_test.go @@ -1019,6 +1019,13 @@ func TestAccWindowsWebApp_updateAppStack(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.healthCheckUpdate(data, "11"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), { Config: r.dotNet(data, "v5.0"), Check: acceptance.ComposeTestCheckFunc( @@ -2569,6 +2576,34 @@ resource "azurerm_windows_web_app" "test" { `, r.baseTemplate(data), data.RandomInteger, javaVersion) } +//nolint:unparam +func (r WindowsWebAppResource) healthCheckUpdate(data acceptance.TestData, javaVersion string) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_windows_web_app" "test" { + name = "acctestWA-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + service_plan_id = azurerm_service_plan.test.id + + site_config { + health_check_path = "/health" + health_check_eviction_time_in_min = 5 + application_stack { + current_stack = "java" + java_version = "%s" + java_embedded_server_enabled = "true" + } + } +} +`, r.baseTemplate(data), data.RandomInteger, javaVersion) +} + func (r WindowsWebAppResource) javaTomcat(data acceptance.TestData, javaVersion string, tomcatVersion string) string { return fmt.Sprintf(` provider "azurerm" { @@ -2610,18 +2645,17 @@ resource "azurerm_windows_web_app" "test" { site_config { application_stack { - dotnet_version = "%s" - php_version = "%s" - python = "%t" - java_version = "%s" - java_container = "%s" - java_container_version = "%s" + dotnet_version = "%s" + php_version = "%s" + python = "%t" + java_version = "%s" + tomcat_version = "%s" current_stack = "python" } } } -`, r.baseTemplate(data), data.RandomInteger, "v4.0", "7.4", true, "1.8", "TOMCAT", "9.0") +`, r.baseTemplate(data), data.RandomInteger, "v4.0", "7.4", true, "1.8", "9.0") } func (r WindowsWebAppResource) withLogsHttpBlob(data acceptance.TestData) string { diff --git a/website/docs/r/windows_web_app.html.markdown b/website/docs/r/windows_web_app.html.markdown index 2056345d303d..abdcb30ee95d 100644 --- a/website/docs/r/windows_web_app.html.markdown +++ b/website/docs/r/windows_web_app.html.markdown @@ -150,6 +150,8 @@ An `application_stack` block supports the following: ~> **NOTE:** Whilst this property is Optional omitting it can cause unexpected behaviour, in particular for display of settings in the Azure Portal. +~> **NOTE:** Windows Web apps can configure multiple `app_stack` properties, it is recommended to always configure this `Optional` value and set it to the primary application stack of your app to ensure correct operation of this resource and display the correct metadata in the Azure Portal. + * `docker_image_name` - (Optional) The docker image, including tag, to be used. e.g. `azure-app-service/windows/parkingpage:latest`. * `docker_registry_url` - (Optional) The URL of the container registry where the `docker_image_name` is located. e.g. `https://index.docker.io` or `https://mcr.microsoft.com`. This value is required with `docker_image_name`.