From a977d725027d2a0e57ec92d651196d60f0d1f3fe Mon Sep 17 00:00:00 2001 From: Praveen Mittal Date: Sat, 24 Oct 2026 13:42:50 +0200 Subject: [PATCH 1/2] fix(alb): accept all documented health check durations --- .../alb/applicationloadbalancer/resource.go | 11 ++++-- .../applicationloadbalancer/resource_test.go | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/stackit/internal/services/alb/applicationloadbalancer/resource.go b/stackit/internal/services/alb/applicationloadbalancer/resource.go index c65da6e28..db3f4d4b6 100644 --- a/stackit/internal/services/alb/applicationloadbalancer/resource.go +++ b/stackit/internal/services/alb/applicationloadbalancer/resource.go @@ -41,6 +41,11 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) +// healthCheckDurationRegex matches the health check durations the error message documents: 0s to +// 999.999s, with up to three decimal places. The alternatives used to be ungrouped, which left the +// first one unanchored at the end and rejected values such as "1.000s". +var healthCheckDurationRegex = regexp.MustCompile(`^[0-9]{1,3}(?:\.[0-9]{1,3})?s$`) + // Ensure the implementation satisfies the expected interfaces. var ( _ resource.Resource = &applicationLoadBalancerResource{} @@ -984,7 +989,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf Required: true, Validators: []validator.String{ stringvalidator.RegexMatches( - regexp.MustCompile(`^[0-9]{1,3}s|[0-9]{1,3}\.(?:[0-9]{2}[1-9]|[0-9][1-9][0-9]|[1-9][0-9]{2})s$`), + healthCheckDurationRegex, "The duration must be between 0s and 999.999s (e.g.: 1s or 0.100s or 12.345s)", ), }, @@ -994,7 +999,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf Required: true, Validators: []validator.String{ stringvalidator.RegexMatches( - regexp.MustCompile(`^[0-9]{1,3}s|[0-9]{1,3}\.(?:[0-9]{2}[1-9]|[0-9][1-9][0-9]|[1-9][0-9]{2})s$`), + healthCheckDurationRegex, "The duration must be between 0s and 999.999s (e.g.: 1s or 0.100s or 12.345s)", ), }, @@ -1004,7 +1009,7 @@ The example below creates the supporting infrastructure using the STACKIT Terraf Required: true, Validators: []validator.String{ stringvalidator.RegexMatches( - regexp.MustCompile(`^[0-9]{1,3}s|[0-9]{1,3}\.(?:[0-9]{2}[1-9]|[0-9][1-9][0-9]|[1-9][0-9]{2})s$`), + healthCheckDurationRegex, "The duration must be between 0s and 999.999s (e.g.: 1s or 0.100s or 12.345s)", ), }, diff --git a/stackit/internal/services/alb/applicationloadbalancer/resource_test.go b/stackit/internal/services/alb/applicationloadbalancer/resource_test.go index 32d1013fa..1270168e1 100644 --- a/stackit/internal/services/alb/applicationloadbalancer/resource_test.go +++ b/stackit/internal/services/alb/applicationloadbalancer/resource_test.go @@ -1679,3 +1679,37 @@ func Test_toPathPayload(t *testing.T) { }) } } + +func TestHealthCheckDurationRegex(t *testing.T) { + tests := []struct { + value string + valid bool + }{ + {"0s", true}, + {"1s", true}, + {"999s", true}, + {"0.1s", true}, + {"0.100s", true}, + {"1.000s", true}, + {"0.000s", true}, + {"12.345s", true}, + {"999.999s", true}, + {"", false}, + {"s", false}, + {"1000s", false}, + {"1.0000s", false}, + {"1.s", false}, + {"-1s", false}, + {"1", false}, + {"1ms", false}, + {"5sGARBAGE", false}, + {"GARBAGE1.000s", false}, + } + for _, tt := range tests { + t.Run(tt.value, func(t *testing.T) { + if got := healthCheckDurationRegex.MatchString(tt.value); got != tt.valid { + t.Errorf("healthCheckDurationRegex.MatchString(%q) = %v, want %v", tt.value, got, tt.valid) + } + }) + } +} From 654e19fa00f9b1b74462f643c353955e536be078 Mon Sep 17 00:00:00 2001 From: Praveen Mittal Date: Wed, 28 Oct 2026 15:19:40 +0100 Subject: [PATCH 2/2] fix(alb): keep the API's duration forms, only anchor the health check regex --- .../services/alb/applicationloadbalancer/resource.go | 8 ++++---- .../alb/applicationloadbalancer/resource_test.go | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/stackit/internal/services/alb/applicationloadbalancer/resource.go b/stackit/internal/services/alb/applicationloadbalancer/resource.go index db3f4d4b6..d86250ebd 100644 --- a/stackit/internal/services/alb/applicationloadbalancer/resource.go +++ b/stackit/internal/services/alb/applicationloadbalancer/resource.go @@ -41,10 +41,10 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) -// healthCheckDurationRegex matches the health check durations the error message documents: 0s to -// 999.999s, with up to three decimal places. The alternatives used to be ungrouped, which left the -// first one unanchored at the end and rejected values such as "1.000s". -var healthCheckDurationRegex = regexp.MustCompile(`^[0-9]{1,3}(?:\.[0-9]{1,3})?s$`) +// healthCheckDurationRegex accepts only durations in the form the API returns them: whole seconds +// ("1s") or exactly three non-zero decimals ("0.100s"), so the value in state matches the config +// and does not drift. The alternatives are grouped so that both are anchored at both ends. +var healthCheckDurationRegex = regexp.MustCompile(`^(?:[0-9]{1,3}s|[0-9]{1,3}\.(?:[0-9]{2}[1-9]|[0-9][1-9][0-9]|[1-9][0-9]{2})s)$`) // Ensure the implementation satisfies the expected interfaces. var ( diff --git a/stackit/internal/services/alb/applicationloadbalancer/resource_test.go b/stackit/internal/services/alb/applicationloadbalancer/resource_test.go index 1270168e1..922e37530 100644 --- a/stackit/internal/services/alb/applicationloadbalancer/resource_test.go +++ b/stackit/internal/services/alb/applicationloadbalancer/resource_test.go @@ -1688,12 +1688,14 @@ func TestHealthCheckDurationRegex(t *testing.T) { {"0s", true}, {"1s", true}, {"999s", true}, - {"0.1s", true}, {"0.100s", true}, - {"1.000s", true}, - {"0.000s", true}, + {"1.500s", true}, {"12.345s", true}, {"999.999s", true}, + // Returned by the API as "0.100s", "1s" and "0s", which would drift. + {"0.1s", false}, + {"1.000s", false}, + {"0.000s", false}, {"", false}, {"s", false}, {"1000s", false}, @@ -1703,7 +1705,8 @@ func TestHealthCheckDurationRegex(t *testing.T) { {"1", false}, {"1ms", false}, {"5sGARBAGE", false}, - {"GARBAGE1.000s", false}, + {"GARBAGE1.500s", false}, + {"5s1.500s", false}, } for _, tt := range tests { t.Run(tt.value, func(t *testing.T) {