From 53cf5b4d7db4c5448aa5758ee4b878d45b289bc7 Mon Sep 17 00:00:00 2001 From: jackofallops <11830746+jackofallops@users.noreply.github.com> Date: Wed, 13 Dec 2023 18:06:46 +0100 Subject: [PATCH] `azurerm_[linux|windows]_web_app[_slot]` - fix a bug in `app_settings` (#24221) * fix bug in processing app_settings a 2nd time * process site_config and app_settings if either has changes * app_settings processing reorder and update node version processing --- .../helpers/common_web_app_schema.go | 14 +++++++++++--- .../appservice/helpers/web_app_slot_schema.go | 16 ++++++++++++++-- .../helpers/windows_web_app_schema.go | 19 +++++++++++++++++-- .../appservice/linux_web_app_resource.go | 8 ++++---- .../appservice/linux_web_app_slot_resource.go | 8 ++++---- .../appservice/windows_web_app_resource.go | 14 ++++---------- .../windows_web_app_slot_resource.go | 14 ++++---------- 7 files changed, 58 insertions(+), 35 deletions(-) diff --git a/internal/services/appservice/helpers/common_web_app_schema.go b/internal/services/appservice/helpers/common_web_app_schema.go index acf958a9ebbb..392aafb4e312 100644 --- a/internal/services/appservice/helpers/common_web_app_schema.go +++ b/internal/services/appservice/helpers/common_web_app_schema.go @@ -1219,10 +1219,18 @@ func FlattenConnectionStrings(appConnectionStrings web.ConnectionStringDictionar return connectionStrings } -func ExpandAppSettingsForUpdate(settings map[string]string) *web.StringDictionary { +func ExpandAppSettingsForUpdate(siteConfigSettings *[]web.NameValuePair) *web.StringDictionary { appSettings := make(map[string]*string) - for k, v := range settings { - appSettings[k] = pointer.To(v) + if siteConfigSettings == nil { + return &web.StringDictionary{ + Properties: appSettings, + } + } + + for _, v := range *siteConfigSettings { + if name := pointer.From(v.Name); name != "" { + appSettings[name] = v.Value + } } return &web.StringDictionary{ diff --git a/internal/services/appservice/helpers/web_app_slot_schema.go b/internal/services/appservice/helpers/web_app_slot_schema.go index b4140bd7fa60..f0ccac9574bf 100644 --- a/internal/services/appservice/helpers/web_app_slot_schema.go +++ b/internal/services/appservice/helpers/web_app_slot_schema.go @@ -993,10 +993,14 @@ func (s *SiteConfigWindowsWebAppSlot) ExpandForCreate(appSettings map[string]str expanded.AppCommandLine = pointer.To(s.AppCommandLine) } - expanded.AppSettings = ExpandAppSettingsForCreate(appSettings) - if len(s.ApplicationStack) == 1 { winAppStack := s.ApplicationStack[0] + if winAppStack.NodeVersion != "" { + if appSettings == nil { + appSettings = make(map[string]string) + } + appSettings["WEBSITE_NODE_DEFAULT_VERSION"] = winAppStack.NodeVersion + } if winAppStack.NetFrameworkVersion != "" { expanded.NetFrameworkVersion = pointer.To(winAppStack.NetFrameworkVersion) } @@ -1027,6 +1031,7 @@ func (s *SiteConfigWindowsWebAppSlot) ExpandForCreate(appSettings map[string]str expanded.JavaContainerVersion = pointer.To(winAppStack.JavaContainerVersion) } } + if !features.FourPointOhBeta() { if winAppStack.DockerContainerName != "" || winAppStack.DockerContainerRegistry != "" || winAppStack.DockerContainerTag != "" { if winAppStack.DockerContainerRegistry != "" { @@ -1051,6 +1056,7 @@ func (s *SiteConfigWindowsWebAppSlot) ExpandForCreate(appSettings map[string]str } else { expanded.WindowsFxVersion = pointer.To("") } + expanded.AppSettings = ExpandAppSettingsForCreate(appSettings) if s.AutoSwapSlotName != "" { @@ -1138,6 +1144,12 @@ func (s *SiteConfigWindowsWebAppSlot) ExpandForUpdate(metadata sdk.ResourceMetaD if metadata.ResourceData.HasChange("site_config.0.application_stack") { if len(s.ApplicationStack) == 1 { winAppStack := s.ApplicationStack[0] + if metadata.ResourceData.HasChange("site_config.0.application_stack.0.node_version") { + if appSettings == nil { + appSettings = make(map[string]string) + } + appSettings["WEBSITE_NODE_DEFAULT_VERSION"] = winAppStack.NodeVersion + } if winAppStack.NetFrameworkVersion != "" { expanded.NetFrameworkVersion = pointer.To(winAppStack.NetFrameworkVersion) } diff --git a/internal/services/appservice/helpers/windows_web_app_schema.go b/internal/services/appservice/helpers/windows_web_app_schema.go index 47aeee577ba9..9d58745d8122 100644 --- a/internal/services/appservice/helpers/windows_web_app_schema.go +++ b/internal/services/appservice/helpers/windows_web_app_schema.go @@ -479,10 +479,14 @@ func (s *SiteConfigWindows) ExpandForCreate(appSettings map[string]string) (*web expanded.AppCommandLine = pointer.To(s.AppCommandLine) } - expanded.AppSettings = ExpandAppSettingsForCreate(appSettings) - if len(s.ApplicationStack) == 1 { winAppStack := s.ApplicationStack[0] + if winAppStack.NodeVersion != "" { + if appSettings == nil { + appSettings = make(map[string]string) + } + appSettings["WEBSITE_NODE_DEFAULT_VERSION"] = winAppStack.NodeVersion + } if winAppStack.NetFrameworkVersion != "" { expanded.NetFrameworkVersion = pointer.To(winAppStack.NetFrameworkVersion) } @@ -513,6 +517,7 @@ func (s *SiteConfigWindows) ExpandForCreate(appSettings map[string]string) (*web expanded.JavaContainerVersion = pointer.To(winAppStack.JavaContainerVersion) } } + if !features.FourPointOhBeta() { if winAppStack.DockerContainerName != "" || winAppStack.DockerContainerRegistry != "" || winAppStack.DockerContainerTag != "" { if winAppStack.DockerContainerRegistry != "" { @@ -535,6 +540,8 @@ func (s *SiteConfigWindows) ExpandForCreate(appSettings map[string]string) (*web expanded.WindowsFxVersion = pointer.To("") } + expanded.AppSettings = ExpandAppSettingsForCreate(appSettings) + if s.ContainerRegistryUserMSI != "" { expanded.AcrUserManagedIdentityID = pointer.To(s.ContainerRegistryUserMSI) } @@ -617,6 +624,12 @@ 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 metadata.ResourceData.HasChange("site_config.0.application_stack.0.node_version") { + if appSettings == nil { + appSettings = make(map[string]string) + } + appSettings["WEBSITE_NODE_DEFAULT_VERSION"] = winAppStack.NodeVersion + } 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 != "": @@ -682,6 +695,8 @@ func (s *SiteConfigWindows) ExpandForUpdate(metadata sdk.ResourceMetaData, exist } } + expanded.AppSettings = ExpandAppSettingsForCreate(appSettings) + if metadata.ResourceData.HasChange("site_config.0.virtual_application") { expanded.VirtualApplications = expandVirtualApplicationsForUpdate(s.VirtualApplications) } else { diff --git a/internal/services/appservice/linux_web_app_resource.go b/internal/services/appservice/linux_web_app_resource.go index e32a12052faf..6d2515431102 100644 --- a/internal/services/appservice/linux_web_app_resource.go +++ b/internal/services/appservice/linux_web_app_resource.go @@ -402,7 +402,7 @@ func (r LinuxWebAppResource) Create() sdk.ResourceFunc { metadata.SetID(id) - appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(webApp.AppSettings) + appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(siteConfig.AppSettings) if metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { appSettingsUpdate.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(webApp.SiteConfig[0].HealthCheckEvictionTime)) } @@ -814,7 +814,7 @@ func (r LinuxWebAppResource) Update() sdk.ResourceFunc { existing.Tags = tags.FromTypedObject(state.Tags) } - if metadata.ResourceData.HasChange("site_config") || servicePlanChange { + if metadata.ResourceData.HasChanges("site_config", "app_settings") || servicePlanChange { existing.SiteConfig, err = sc.ExpandForUpdate(metadata, existing.SiteConfig, state.AppSettings) if err != nil { return err @@ -855,8 +855,8 @@ func (r LinuxWebAppResource) Update() sdk.ResourceFunc { } // (@jackofallops) - App Settings can clobber logs configuration so must be updated before we send any Log updates - if metadata.ResourceData.HasChange("app_settings") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { - appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(state.AppSettings) + if metadata.ResourceData.HasChanges("app_settings", "site_config") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { + appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(existing.SiteConfig.AppSettings) appSettingsUpdate.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(state.SiteConfig[0].HealthCheckEvictionTime)) if _, err := client.UpdateApplicationSettings(ctx, id.ResourceGroup, id.SiteName, *appSettingsUpdate); err != nil { diff --git a/internal/services/appservice/linux_web_app_slot_resource.go b/internal/services/appservice/linux_web_app_slot_resource.go index cda9670501c7..c7605347b05c 100644 --- a/internal/services/appservice/linux_web_app_slot_resource.go +++ b/internal/services/appservice/linux_web_app_slot_resource.go @@ -391,7 +391,7 @@ func (r LinuxWebAppSlotResource) Create() sdk.ResourceFunc { metadata.SetID(id) - appSettings := helpers.ExpandAppSettingsForUpdate(webAppSlot.AppSettings) + appSettings := helpers.ExpandAppSettingsForUpdate(siteConfig.AppSettings) if metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { appSettings.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(webAppSlot.SiteConfig[0].HealthCheckEvictionTime)) } @@ -813,7 +813,7 @@ func (r LinuxWebAppSlotResource) Update() sdk.ResourceFunc { existing.Tags = tags.FromTypedObject(state.Tags) } - if metadata.ResourceData.HasChange("site_config") { + if metadata.ResourceData.HasChanges("site_config", "app_settings") { sc := state.SiteConfig[0] siteConfig, err := sc.ExpandForUpdate(metadata, existing.SiteConfig, state.AppSettings) if err != nil { @@ -856,8 +856,8 @@ func (r LinuxWebAppSlotResource) Update() sdk.ResourceFunc { } // (@jackofallops) - App Settings can clobber logs configuration so must be updated before we send any Log updates - if metadata.ResourceData.HasChange("app_settings") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { - appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(state.AppSettings) + if metadata.ResourceData.HasChanges("app_settings", "site_config") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { + appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(existing.SiteConfig.AppSettings) appSettingsUpdate.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(state.SiteConfig[0].HealthCheckEvictionTime)) if _, err := client.UpdateApplicationSettingsSlot(ctx, id.ResourceGroup, id.SiteName, *appSettingsUpdate, id.SlotName); err != nil { diff --git a/internal/services/appservice/windows_web_app_resource.go b/internal/services/appservice/windows_web_app_resource.go index ec45ee73cc30..a306e469dc44 100644 --- a/internal/services/appservice/windows_web_app_resource.go +++ b/internal/services/appservice/windows_web_app_resource.go @@ -351,12 +351,6 @@ func (r WindowsWebAppResource) Create() sdk.ResourceFunc { currentStack := "" if len(sc.ApplicationStack) == 1 { currentStack = sc.ApplicationStack[0].CurrentStack - if currentStack == helpers.CurrentStackNode || sc.ApplicationStack[0].NodeVersion != "" { - if webApp.AppSettings == nil { - webApp.AppSettings = make(map[string]string, 0) - } - webApp.AppSettings["WEBSITE_NODE_DEFAULT_VERSION"] = sc.ApplicationStack[0].NodeVersion - } } expandedIdentity, err := expandIdentity(metadata.ResourceData.Get("identity").([]interface{})) @@ -420,7 +414,7 @@ func (r WindowsWebAppResource) Create() sdk.ResourceFunc { } } - appSettings := helpers.ExpandAppSettingsForUpdate(webApp.AppSettings) + appSettings := helpers.ExpandAppSettingsForUpdate(siteConfig.AppSettings) if metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { appSettings.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(webApp.SiteConfig[0].HealthCheckEvictionTime)) } @@ -878,7 +872,7 @@ func (r WindowsWebAppResource) Update() sdk.ResourceFunc { currentStack = sc.ApplicationStack[0].CurrentStack } - if metadata.ResourceData.HasChange("site_config") || servicePlanChange { + if metadata.ResourceData.HasChanges("site_config", "app_settings") || servicePlanChange { existing.SiteConfig, err = sc.ExpandForUpdate(metadata, existing.SiteConfig, state.AppSettings) if err != nil { return err @@ -912,8 +906,8 @@ func (r WindowsWebAppResource) Update() sdk.ResourceFunc { } // (@jackofallops) - App Settings can clobber logs configuration so must be updated before we send any Log updates - if metadata.ResourceData.HasChange("app_settings") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { - appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(state.AppSettings) + if metadata.ResourceData.HasChanges("app_settings", "site_config") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { + appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(existing.SiteConfig.AppSettings) appSettingsUpdate.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(state.SiteConfig[0].HealthCheckEvictionTime)) if _, err := client.UpdateApplicationSettings(ctx, id.ResourceGroup, id.SiteName, *appSettingsUpdate); err != nil { return fmt.Errorf("updating App Settings for Windows %s: %+v", id, err) diff --git a/internal/services/appservice/windows_web_app_slot_resource.go b/internal/services/appservice/windows_web_app_slot_resource.go index 9b7034643f96..742dea72aba2 100644 --- a/internal/services/appservice/windows_web_app_slot_resource.go +++ b/internal/services/appservice/windows_web_app_slot_resource.go @@ -332,12 +332,6 @@ func (r WindowsWebAppSlotResource) Create() sdk.ResourceFunc { currentStack := "" if len(sc.ApplicationStack) == 1 { currentStack = sc.ApplicationStack[0].CurrentStack - if currentStack == helpers.CurrentStackNode || sc.ApplicationStack[0].NodeVersion != "" { - if webAppSlot.AppSettings == nil { - webAppSlot.AppSettings = make(map[string]string, 0) - } - webAppSlot.AppSettings["WEBSITE_NODE_DEFAULT_VERSION"] = sc.ApplicationStack[0].NodeVersion - } } expandedIdentity, err := expandIdentity(metadata.ResourceData.Get("identity").([]interface{})) @@ -407,7 +401,7 @@ func (r WindowsWebAppSlotResource) Create() sdk.ResourceFunc { } } - appSettings := helpers.ExpandAppSettingsForUpdate(webAppSlot.AppSettings) + appSettings := helpers.ExpandAppSettingsForUpdate(siteConfig.AppSettings) if metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") { appSettings.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(webAppSlot.SiteConfig[0].HealthCheckEvictionTime)) } @@ -839,7 +833,7 @@ func (r WindowsWebAppSlotResource) Update() sdk.ResourceFunc { currentStack = sc.ApplicationStack[0].CurrentStack } - if metadata.ResourceData.HasChange("site_config") { + if metadata.ResourceData.HasChanges("site_config", "app_settings") { existing.SiteConfig, err = sc.ExpandForUpdate(metadata, existing.SiteConfig, state.AppSettings) if err != nil { return err @@ -895,8 +889,8 @@ func (r WindowsWebAppSlotResource) Update() sdk.ResourceFunc { } // (@jackofallops) - App Settings can clobber logs configuration so must be updated before we send any Log updates - if metadata.ResourceData.HasChange("app_settings") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") || metadata.ResourceData.HasChange("site_config.0.application_stack.0.node_version") { - appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(state.AppSettings) + if metadata.ResourceData.HasChanges("app_settings", "site_config") || metadata.ResourceData.HasChange("site_config.0.health_check_eviction_time_in_min") || metadata.ResourceData.HasChange("site_config.0.application_stack.0.node_version") { + appSettingsUpdate := helpers.ExpandAppSettingsForUpdate(existing.SiteConfig.AppSettings) appSettingsUpdate.Properties["WEBSITE_HEALTHCHECK_MAXPINGFAILURES"] = pointer.To(strconv.Itoa(state.SiteConfig[0].HealthCheckEvictionTime)) appSettingsUpdate.Properties["WEBSITE_NODE_DEFAULT_VERSION"] = pointer.To(state.SiteConfig[0].ApplicationStack[0].NodeVersion) if _, err := client.UpdateApplicationSettingsSlot(ctx, id.ResourceGroup, id.SiteName, *appSettingsUpdate, id.SlotName); err != nil {