From 7cc244e41c05f5dd47d2e4e1999cb42a6368c1c9 Mon Sep 17 00:00:00 2001 From: Sueeda Oezkaya Date: Thu, 16 Jul 2026 18:56:39 +0200 Subject: [PATCH 1/4] bugfix: add plan-time regex validation for telemetry link name and description --- .../services/telemetrylink/link/resource.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/stackit/internal/services/telemetrylink/link/resource.go b/stackit/internal/services/telemetrylink/link/resource.go index 5227bca1b..f060330c6 100644 --- a/stackit/internal/services/telemetrylink/link/resource.go +++ b/stackit/internal/services/telemetrylink/link/resource.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "regexp" "strings" "time" @@ -172,10 +173,22 @@ func (r *telemetryLinkResource) Schema(_ context.Context, _ resource.SchemaReque "display_name": schema.StringAttribute{ Description: schemaDescriptions["display_name"], Required: true, + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\ ]*$`), + "The display name must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), + }, }, "description": schema.StringAttribute{ Description: schemaDescriptions["description"], Optional: true, + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\ ]*$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), + }, }, "region": schema.StringAttribute{ Description: schemaDescriptions["region"], From eb638adce55888ce07c514d257f4cffc72093960 Mon Sep 17 00:00:00 2001 From: Sueeda Oezkaya Date: Thu, 23 Jul 2026 11:28:57 +0200 Subject: [PATCH 2/4] match validation for telemetry router and telemetry link with api --- .../internal/services/telemetrylink/link/resource.go | 12 +++++++----- .../services/telemetryrouter/accesstoken/resource.go | 12 ++++++++++++ .../services/telemetryrouter/destination/resource.go | 11 +++++++++++ .../services/telemetryrouter/instance/resource.go | 11 +++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/stackit/internal/services/telemetrylink/link/resource.go b/stackit/internal/services/telemetrylink/link/resource.go index f060330c6..d1f82cbb9 100644 --- a/stackit/internal/services/telemetrylink/link/resource.go +++ b/stackit/internal/services/telemetrylink/link/resource.go @@ -174,8 +174,9 @@ func (r *telemetryLinkResource) Schema(_ context.Context, _ resource.SchemaReque Description: schemaDescriptions["display_name"], Required: true, Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), stringvalidator.RegexMatches( - regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\ ]*$`), + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), "The display name must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", ), }, @@ -184,10 +185,11 @@ func (r *telemetryLinkResource) Schema(_ context.Context, _ resource.SchemaReque Description: schemaDescriptions["description"], Optional: true, Validators: []validator.String{ - stringvalidator.RegexMatches( - regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9\-\ ]*$`), - "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", - ), + stringvalidator.LengthAtMost(1024), + stringvalidator.RegexMatches( + regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), }, }, "region": schema.StringAttribute{ diff --git a/stackit/internal/services/telemetryrouter/accesstoken/resource.go b/stackit/internal/services/telemetryrouter/accesstoken/resource.go index 4b50c427a..6ff3f69d7 100644 --- a/stackit/internal/services/telemetryrouter/accesstoken/resource.go +++ b/stackit/internal/services/telemetryrouter/accesstoken/resource.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "regexp" "strings" "time" @@ -14,6 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/int32planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -172,6 +174,13 @@ func (r *telemetryRouterAccessTokenResource) Schema(_ context.Context, _ resourc "display_name": schema.StringAttribute{ Description: schemaDescriptions["display_name"], Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "region": schema.StringAttribute{ Description: schemaDescriptions["region"], @@ -185,6 +194,9 @@ func (r *telemetryRouterAccessTokenResource) Schema(_ context.Context, _ resourc "description": schema.StringAttribute{ Description: schemaDescriptions["description"], Optional: true, + Validators: []validator.String{ + stringvalidator.LengthAtMost(1024), + }, }, "ttl": schema.Int32Attribute{ Description: schemaDescriptions["ttl"], diff --git a/stackit/internal/services/telemetryrouter/destination/resource.go b/stackit/internal/services/telemetryrouter/destination/resource.go index 692ee7648..7d975f5f5 100644 --- a/stackit/internal/services/telemetryrouter/destination/resource.go +++ b/stackit/internal/services/telemetryrouter/destination/resource.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "regexp" "strings" "time" @@ -293,6 +294,13 @@ func (r *telemetryRouterDestinationResource) Schema(_ context.Context, _ resourc "display_name": schema.StringAttribute{ Description: schemaDescriptions["display_name"], Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "config": schema.SingleNestedAttribute{ Description: schemaDescriptions["config"], @@ -420,6 +428,9 @@ func (r *telemetryRouterDestinationResource) Schema(_ context.Context, _ resourc "description": schema.StringAttribute{ Description: schemaDescriptions["description"], Optional: true, + Validators: []validator.String{ + stringvalidator.LengthAtMost(1024), + }, }, "creation_time": schema.StringAttribute{ Description: schemaDescriptions["creation_time"], diff --git a/stackit/internal/services/telemetryrouter/instance/resource.go b/stackit/internal/services/telemetryrouter/instance/resource.go index 2ae17edc0..dff547b79 100644 --- a/stackit/internal/services/telemetryrouter/instance/resource.go +++ b/stackit/internal/services/telemetryrouter/instance/resource.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "regexp" "strings" "time" @@ -195,6 +196,13 @@ func (r *telemetryRouterInstanceResource) Schema(_ context.Context, _ resource.S "display_name": schema.StringAttribute{ Description: schemaDescriptions["display_name"], Required: true, + Validators: []validator.String{ + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "region": schema.StringAttribute{ Description: schemaDescriptions["region"], @@ -208,6 +216,9 @@ func (r *telemetryRouterInstanceResource) Schema(_ context.Context, _ resource.S "description": schema.StringAttribute{ Description: schemaDescriptions["description"], Optional: true, + Validators: []validator.String{ + stringvalidator.LengthAtMost(1024), + }, }, "filter": schema.SingleNestedAttribute{ Description: schemaDescriptions["filter"], From fe94e50cab9cea0b4c5335e3575cd7de5788f5f2 Mon Sep 17 00:00:00 2001 From: Sueeda Oezkaya Date: Fri, 7 Aug 2026 09:27:09 +0200 Subject: [PATCH 3/4] bugfix: add missing validation for telemetry router display name and description --- .../services/telemetrylink/link/resource.go | 8 +++---- .../telemetryrouter/accesstoken/resource.go | 22 +++++++++++-------- .../telemetryrouter/destination/resource.go | 20 ++++++++++------- .../telemetryrouter/instance/resource.go | 20 ++++++++++------- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/stackit/internal/services/telemetrylink/link/resource.go b/stackit/internal/services/telemetrylink/link/resource.go index d1f82cbb9..15b399e90 100644 --- a/stackit/internal/services/telemetrylink/link/resource.go +++ b/stackit/internal/services/telemetrylink/link/resource.go @@ -186,10 +186,10 @@ func (r *telemetryLinkResource) Schema(_ context.Context, _ resource.SchemaReque Optional: true, Validators: []validator.String{ stringvalidator.LengthAtMost(1024), - stringvalidator.RegexMatches( - regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), - "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", - ), + stringvalidator.RegexMatches( + regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), }, }, "region": schema.StringAttribute{ diff --git a/stackit/internal/services/telemetryrouter/accesstoken/resource.go b/stackit/internal/services/telemetryrouter/accesstoken/resource.go index 6ff3f69d7..471c03069 100644 --- a/stackit/internal/services/telemetryrouter/accesstoken/resource.go +++ b/stackit/internal/services/telemetryrouter/accesstoken/resource.go @@ -9,13 +9,13 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/int32planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -175,12 +175,12 @@ func (r *telemetryRouterAccessTokenResource) Schema(_ context.Context, _ resourc Description: schemaDescriptions["display_name"], Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 32), - stringvalidator.RegexMatches( - regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", - ), - }, + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "region": schema.StringAttribute{ Description: schemaDescriptions["region"], @@ -195,8 +195,12 @@ func (r *telemetryRouterAccessTokenResource) Schema(_ context.Context, _ resourc Description: schemaDescriptions["description"], Optional: true, Validators: []validator.String{ - stringvalidator.LengthAtMost(1024), - }, + stringvalidator.LengthAtMost(1024), + stringvalidator.RegexMatches( + regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), + }, }, "ttl": schema.Int32Attribute{ Description: schemaDescriptions["ttl"], diff --git a/stackit/internal/services/telemetryrouter/destination/resource.go b/stackit/internal/services/telemetryrouter/destination/resource.go index 7d975f5f5..1d9ae6f9c 100644 --- a/stackit/internal/services/telemetryrouter/destination/resource.go +++ b/stackit/internal/services/telemetryrouter/destination/resource.go @@ -295,12 +295,12 @@ func (r *telemetryRouterDestinationResource) Schema(_ context.Context, _ resourc Description: schemaDescriptions["display_name"], Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 32), - stringvalidator.RegexMatches( - regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", - ), - }, + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "config": schema.SingleNestedAttribute{ Description: schemaDescriptions["config"], @@ -429,8 +429,12 @@ func (r *telemetryRouterDestinationResource) Schema(_ context.Context, _ resourc Description: schemaDescriptions["description"], Optional: true, Validators: []validator.String{ - stringvalidator.LengthAtMost(1024), - }, + stringvalidator.LengthAtMost(1024), + stringvalidator.RegexMatches( + regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), + }, }, "creation_time": schema.StringAttribute{ Description: schemaDescriptions["creation_time"], diff --git a/stackit/internal/services/telemetryrouter/instance/resource.go b/stackit/internal/services/telemetryrouter/instance/resource.go index dff547b79..685f306ab 100644 --- a/stackit/internal/services/telemetryrouter/instance/resource.go +++ b/stackit/internal/services/telemetryrouter/instance/resource.go @@ -197,12 +197,12 @@ func (r *telemetryRouterInstanceResource) Schema(_ context.Context, _ resource.S Description: schemaDescriptions["display_name"], Required: true, Validators: []validator.String{ - stringvalidator.LengthBetween(1, 32), - stringvalidator.RegexMatches( - regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", - ), - }, + stringvalidator.LengthBetween(1, 32), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), + "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + ), + }, }, "region": schema.StringAttribute{ Description: schemaDescriptions["region"], @@ -217,8 +217,12 @@ func (r *telemetryRouterInstanceResource) Schema(_ context.Context, _ resource.S Description: schemaDescriptions["description"], Optional: true, Validators: []validator.String{ - stringvalidator.LengthAtMost(1024), - }, + stringvalidator.LengthAtMost(1024), + stringvalidator.RegexMatches( + regexp.MustCompile(`^([a-zA-Z0-9][a-zA-Z0-9 \-]*)?$`), + "The description must start with an alphanumeric character and can only contain letters, numbers, spaces, and hyphens.", + ), + }, }, "filter": schema.SingleNestedAttribute{ Description: schemaDescriptions["filter"], From f332f2b562897585c9af4f0c318bef33c5876ba9 Mon Sep 17 00:00:00 2001 From: Sueeda Oezkaya Date: Tue, 11 Aug 2026 15:36:18 +0200 Subject: [PATCH 4/4] Update error message text --- .../internal/services/telemetryrouter/accesstoken/resource.go | 2 +- .../internal/services/telemetryrouter/destination/resource.go | 2 +- stackit/internal/services/telemetryrouter/instance/resource.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stackit/internal/services/telemetryrouter/accesstoken/resource.go b/stackit/internal/services/telemetryrouter/accesstoken/resource.go index 471c03069..07b65c7fb 100644 --- a/stackit/internal/services/telemetryrouter/accesstoken/resource.go +++ b/stackit/internal/services/telemetryrouter/accesstoken/resource.go @@ -178,7 +178,7 @@ func (r *telemetryRouterAccessTokenResource) Schema(_ context.Context, _ resourc stringvalidator.LengthBetween(1, 32), stringvalidator.RegexMatches( regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + "The display name must start with an alphanumeric character and can contain only letters, numbers, spaces, and hyphens.", ), }, }, diff --git a/stackit/internal/services/telemetryrouter/destination/resource.go b/stackit/internal/services/telemetryrouter/destination/resource.go index 1d9ae6f9c..2206a6f3d 100644 --- a/stackit/internal/services/telemetryrouter/destination/resource.go +++ b/stackit/internal/services/telemetryrouter/destination/resource.go @@ -298,7 +298,7 @@ func (r *telemetryRouterDestinationResource) Schema(_ context.Context, _ resourc stringvalidator.LengthBetween(1, 32), stringvalidator.RegexMatches( regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + "The display name must start with an alphanumeric character and can contain only letters, numbers, spaces, and hyphens.", ), }, }, diff --git a/stackit/internal/services/telemetryrouter/instance/resource.go b/stackit/internal/services/telemetryrouter/instance/resource.go index 685f306ab..88d608bf5 100644 --- a/stackit/internal/services/telemetryrouter/instance/resource.go +++ b/stackit/internal/services/telemetryrouter/instance/resource.go @@ -200,7 +200,7 @@ func (r *telemetryRouterInstanceResource) Schema(_ context.Context, _ resource.S stringvalidator.LengthBetween(1, 32), stringvalidator.RegexMatches( regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9 \-]*$`), - "must start with an alphanumeric character and contain only alphanumeric characters, spaces, and hyphens", + "The display name must start with an alphanumeric character and can contain only letters, numbers, spaces, and hyphens.", ), }, },