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

azurerm_windows_web_app, azurerm_windows_web_app_slot, azurerm_linux_web_app, azurerm_linux _web_app_slot - fix auto heal slow request with path issue #20049

Merged
merged 13 commits into from
May 7, 2024
182 changes: 174 additions & 8 deletions internal/services/appservice/helpers/auto_heal.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/Azure/azure-sdk-for-go/services/web/mgmt/2021-02-01/web" // nolint: staticcheck
"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
Expand All @@ -17,10 +18,11 @@ type AutoHealSettingWindows struct {
}

type AutoHealTriggerWindows struct {
Requests []AutoHealRequestTrigger `tfschema:"requests"`
PrivateMemoryKB int `tfschema:"private_memory_kb"` // Private should be > 102400 KB (100 MB) to 13631488 KB (13 GB), defaults to 0 however and is always present.
StatusCodes []AutoHealStatusCodeTrigger `tfschema:"status_code"` // 0 or more, ranges split by `-`, ranges cannot use sub-status or win32 code
SlowRequests []AutoHealSlowRequest `tfschema:"slow_request"`
Requests []AutoHealRequestTrigger `tfschema:"requests"`
PrivateMemoryKB int `tfschema:"private_memory_kb"` // Private should be > 102400 KB (100 MB) to 13631488 KB (13 GB), defaults to 0 however and is always present.
StatusCodes []AutoHealStatusCodeTrigger `tfschema:"status_code"` // 0 or more, ranges split by `-`, ranges cannot use sub-status or win32 code
SlowRequests []AutoHealSlowRequest `tfschema:"slow_request"`
SlowRequestsWithPath []AutoHealSlowRequestWithPath `tfschema:"slow_request_with_path"`
}

type AutoHealRequestTrigger struct {
Expand All @@ -44,6 +46,13 @@ type AutoHealSlowRequest struct {
Path string `tfschema:"path"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be able to remove this from the schema below, the struct needs to be tagged as below or we'll get a error in decoding.

Suggested change
Path string `tfschema:"path"`
Path string `tfschema:"path,removedInNextMajorVersion"`

}

type AutoHealSlowRequestWithPath struct {
TimeTaken string `tfschema:"time_taken"`
Interval string `tfschema:"interval"`
Count int `tfschema:"count"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Count int `tfschema:"count"`
Count int64 `tfschema:"count"`

Path string `tfschema:"path"`
}
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved

type AutoHealActionWindows struct {
ActionType string `tfschema:"action_type"` // Enum
CustomAction []AutoHealCustomAction `tfschema:"custom_action"` // Max: 1, needs `action_type` to be "Custom"
Expand Down Expand Up @@ -176,7 +185,7 @@ func autoHealActionSchemaWindowsComputed() *pluginsdk.Schema {

// (@jackofallops) - trigger schemas intentionally left long-hand for now
func autoHealTriggerSchemaWindows() *pluginsdk.Schema {
return &pluginsdk.Schema{
s := &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Required: true,
MaxItems: 1,
Expand Down Expand Up @@ -274,6 +283,32 @@ func autoHealTriggerSchemaWindows() *pluginsdk.Schema {
Required: true,
ValidateFunc: validation.IntAtLeast(1),
},
},
},
},

"slow_request_with_path": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"time_taken": {
Type: pluginsdk.TypeString,
Required: true,
// ValidateFunc: validation.IsRFC3339Time,
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved
},

"interval": {
Type: pluginsdk.TypeString,
Required: true,
// ValidateFunc: validation.IsRFC3339Time,
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved
},

"count": {
Type: pluginsdk.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
},

"path": {
Type: pluginsdk.TypeString,
Expand All @@ -286,10 +321,45 @@ func autoHealTriggerSchemaWindows() *pluginsdk.Schema {
},
},
}
if !features.FourPointOhBeta() {
s.Elem.(*pluginsdk.Resource).Schema["slow_request"] = &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Optional: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"time_taken": {
Type: pluginsdk.TypeString,
Required: true,
// ValidateFunc: validation.IsRFC3339Time,
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved
},

"interval": {
Type: pluginsdk.TypeString,
Required: true,
// ValidateFunc: validation.IsRFC3339Time,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have validation here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},

"count": {
Type: pluginsdk.TypeInt,
Required: true,
ValidateFunc: validation.IntAtLeast(1),
},

"path": {
xiaxyi marked this conversation as resolved.
Show resolved Hide resolved
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
},
}
}
return s
}

func autoHealTriggerSchemaWindowsComputed() *pluginsdk.Schema {
return &pluginsdk.Schema{
s := &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Expand Down Expand Up @@ -356,6 +426,29 @@ func autoHealTriggerSchemaWindowsComputed() *pluginsdk.Schema {
},

"slow_request": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"time_taken": {
Type: pluginsdk.TypeString,
Computed: true,
},

"interval": {
Type: pluginsdk.TypeString,
Computed: true,
},

"count": {
Type: pluginsdk.TypeInt,
Computed: true,
},
},
},
},

"slow_request_with_path": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Expand Down Expand Up @@ -385,6 +478,36 @@ func autoHealTriggerSchemaWindowsComputed() *pluginsdk.Schema {
},
},
}
if !features.FourPointOh() {
s.Elem.(*pluginsdk.Resource).Schema["slow_request"] = &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"time_taken": {
Type: pluginsdk.TypeString,
Computed: true,
},

"interval": {
Type: pluginsdk.TypeString,
Computed: true,
},

"count": {
Type: pluginsdk.TypeInt,
Computed: true,
},

"path": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
},
}
}
return s
}

func expandAutoHealSettingsWindows(autoHealSettings []AutoHealSettingWindows) *web.AutoHealRules {
Expand Down Expand Up @@ -413,11 +536,29 @@ func expandAutoHealSettingsWindows(autoHealSettings []AutoHealSettingWindows) *w
TimeInterval: pointer.To(triggers.SlowRequests[0].Interval),
Count: pointer.To(int32(triggers.SlowRequests[0].Count)),
}
if triggers.SlowRequests[0].Path != "" {
result.Triggers.SlowRequests.Path = pointer.To(triggers.SlowRequests[0].Path)
if !features.FourPointOh() {
if triggers.SlowRequests[0].Path != "" {
result.Triggers.SlowRequests.Path = pointer.To(triggers.SlowRequests[0].Path)
}
}
}

if len(triggers.SlowRequestsWithPath) > 0 {
slowRequestWithPathTriggers := make([]web.SlowRequestsBasedTrigger, 0)
for _, sr := range triggers.SlowRequestsWithPath {
trigger := web.SlowRequestsBasedTrigger{
TimeTaken: pointer.To(sr.TimeTaken),
TimeInterval: pointer.To(sr.Interval),
Count: pointer.To(int32(sr.Count)),
}
if sr.Path != "" {
trigger.Path = pointer.To(sr.Path)
}
slowRequestWithPathTriggers = append(slowRequestWithPathTriggers, trigger)
}
result.Triggers.SlowRequestsWithPath = &slowRequestWithPathTriggers
}

if triggers.PrivateMemoryKB != 0 {
result.Triggers.PrivateBytesInKB = pointer.To(int32(triggers.PrivateMemoryKB))
}
Expand All @@ -444,6 +585,12 @@ func expandAutoHealSettingsWindows(autoHealSettings []AutoHealSettingWindows) *w
}
statusCodeTrigger.Count = pointer.To(int32(s.Count))
statusCodeTrigger.TimeInterval = pointer.To(s.Interval)
if s.Win32Status != "" {
win32Code, err := strconv.Atoi(s.Win32Status)
if err == nil {
statusCodeTrigger.Win32Status = pointer.To(int32(win32Code))
}
}
if s.Path != "" {
statusCodeTrigger.Path = pointer.To(s.Path)
}
Expand Down Expand Up @@ -512,6 +659,10 @@ func flattenAutoHealSettingsWindows(autoHealRules *web.AutoHealRules) []AutoHeal
if s.SubStatus != nil {
t.SubStatus = int(*s.SubStatus)
}

if s.Win32Status != nil {
t.Win32Status = strconv.Itoa(int(*s.Win32Status))
}
statusCodeTriggers = append(statusCodeTriggers, t)
}
}
Expand Down Expand Up @@ -542,7 +693,22 @@ func flattenAutoHealSettingsWindows(autoHealRules *web.AutoHealRules) []AutoHeal
Path: pointer.From(triggers.SlowRequests.Path),
})
}

slowRequestTriggersWithPaths := make([]AutoHealSlowRequestWithPath, 0)
if triggers.SlowRequestsWithPath != nil {
for _, v := range *triggers.SlowRequestsWithPath {
sr := AutoHealSlowRequestWithPath{
TimeTaken: pointer.From(v.TimeTaken),
Interval: pointer.From(v.TimeInterval),
Count: int(pointer.From(v.Count)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Count: int(pointer.From(v.Count)),
Count: pointer.From(v.Count),

Path: pointer.From(v.Path),
}
slowRequestTriggersWithPaths = append(slowRequestTriggersWithPaths, sr)
}
}

resultTrigger.SlowRequests = slowRequestTriggers
resultTrigger.SlowRequestsWithPath = slowRequestTriggersWithPaths
result.Triggers = []AutoHealTriggerWindows{resultTrigger}
}

Expand Down
Loading