diff --git a/CHANGELOG.md b/CHANGELOG.md index 8067f2c48a..432f0b7bbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## main / unreleased +## 3.7.2 / 2025-10-22 + +* [BUGFIX] AWS SD: Fix AWS SDK v2 credentials handling for EC2 and Lightsail discovery. #17355 +* [BUGFIX] AWS SD: Load AWS region from IMDS when not set. #17376 +* [BUGFIX] Relabeling: Fix `labelmap` action validation with the legacy metric name validation scheme. #17372 +* [BUGFIX] PromQL: Fix parsing failure when `anchored` and `smoothed` are used as metric names and label names. #17353 +* [BUGFIX] PromQL: Fix formatting of range vector selectors with `smoothed`/`anchored` modifier. #17354 + ## 3.7.1 / 2025-10-16 * [BUGFIX] OTLP: Prefix `key_` to label name when translating an OTel attribute name starting with a single underscore, and keep multiple consecutive underscores in label name when translating an OTel attribute name. This reverts the breaking changes introduced in 3.7.0. #17344 @@ -48,7 +56,7 @@ * [BUGFIX] TSDB: Avoid misleading `Failed to calculate size of \"wal\" dir` error logs during WAL clean-up. #17006 * [BUGFIX] TSDB: Prevent erroneously dropping series records during WAL checkpoints. #17029 * [BUGFIX] UI: Fix redirect to path of `-web.external-url` if `-web.route-prefix` is configured. #17240 -* [BUGIFX] Remote-write: Do not panic on invalid symbol table in remote-write 2.0. #17160 +* [BUGFIX] Remote-write: Do not panic on invalid symbol table in remote-write 2.0. #17160 ## 3.6.0 / 2025-09-17 diff --git a/VERSION b/VERSION index a76ccff2a6..0b2eb36f50 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.7.1 +3.7.2 diff --git a/discovery/aws/ec2.go b/discovery/aws/ec2.go index 539cd84c4f..0386d9bb1c 100644 --- a/discovery/aws/ec2.go +++ b/discovery/aws/ec2.go @@ -27,6 +27,7 @@ import ( awsConfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/credentials/stscreds" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/aws/aws-sdk-go-v2/service/sts" @@ -123,6 +124,7 @@ func (c *EC2SDConfig) UnmarshalYAML(unmarshal func(any) error) error { if err != nil { return err } + if c.Region == "" { cfg, err := awsConfig.LoadDefaultConfig(context.Background()) if err != nil { @@ -134,6 +136,16 @@ func (c *EC2SDConfig) UnmarshalYAML(unmarshal func(any) error) error { // This can happen if the user has set the region in the AWS config file or environment variables. c.Region = cfg.Region } + + if c.Region == "" { + // Try to get the region from the instance metadata service (IMDS). + imdsClient := imds.NewFromConfig(cfg) + region, err := imdsClient.GetRegion(context.Background(), &imds.GetRegionInput{}) + if err != nil { + return err + } + c.Region = region.Region + } } if c.Region == "" { @@ -197,7 +209,6 @@ func (d *EC2Discovery) ec2Client(ctx context.Context) (ec2Client, error) { if d.ec2 != nil { return d.ec2, nil } - credProvider := credentials.NewStaticCredentialsProvider(d.cfg.AccessKey, string(d.cfg.SecretKey), "") // Build the HTTP client from the provided HTTPClientConfig. httpClient, err := config.NewClientFromConfig(d.cfg.HTTPClientConfig, "ec2_sd") @@ -205,14 +216,25 @@ func (d *EC2Discovery) ec2Client(ctx context.Context) (ec2Client, error) { return nil, err } - // Build the AWS config with the provided region and credentials. - cfg, err := awsConfig.LoadDefaultConfig( - ctx, + // Build the AWS config with the provided region. + configOptions := []func(*awsConfig.LoadOptions) error{ awsConfig.WithRegion(d.cfg.Region), - awsConfig.WithCredentialsProvider(credProvider), - awsConfig.WithSharedConfigProfile(d.cfg.Profile), awsConfig.WithHTTPClient(httpClient), - ) + } + + // Only set static credentials if both access key and secret key are provided. + // Otherwise, let the AWS SDK use its default credential chain (environment variables, IAM role, etc.). + if d.cfg.AccessKey != "" && d.cfg.SecretKey != "" { + credProvider := credentials.NewStaticCredentialsProvider(d.cfg.AccessKey, string(d.cfg.SecretKey), "") + configOptions = append(configOptions, awsConfig.WithCredentialsProvider(credProvider)) + } + + // Set the profile if provided. + if d.cfg.Profile != "" { + configOptions = append(configOptions, awsConfig.WithSharedConfigProfile(d.cfg.Profile)) + } + + cfg, err := awsConfig.LoadDefaultConfig(ctx, configOptions...) if err != nil { return nil, fmt.Errorf("could not create aws config: %w", err) } diff --git a/discovery/aws/lightsail.go b/discovery/aws/lightsail.go index 5c356c8c45..5441e510b9 100644 --- a/discovery/aws/lightsail.go +++ b/discovery/aws/lightsail.go @@ -27,6 +27,7 @@ import ( awsConfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/credentials/stscreds" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/aws/aws-sdk-go-v2/service/lightsail" "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/aws/smithy-go" @@ -105,14 +106,27 @@ func (c *LightsailSDConfig) UnmarshalYAML(unmarshal func(any) error) error { if err != nil { return err } + if c.Region == "" { cfg, err := awsConfig.LoadDefaultConfig(context.Background()) if err != nil { return err } - // Use the region from the AWS config. It will load environment variables and shared config files. - c.Region = cfg.Region + if cfg.Region != "" { + // Use the region from the AWS config. It will load environment variables and shared config files. + c.Region = cfg.Region + } + + if c.Region == "" { + // Try to get the region from the instance metadata service (IMDS). + imdsClient := imds.NewFromConfig(cfg) + region, err := imdsClient.GetRegion(context.Background(), &imds.GetRegionInput{}) + if err != nil { + return err + } + c.Region = region.Region + } } if c.Region == "" { @@ -161,22 +175,31 @@ func (d *LightsailDiscovery) lightsailClient(ctx context.Context) (*lightsail.Cl return d.lightsail, nil } - credProvider := credentials.NewStaticCredentialsProvider(d.cfg.AccessKey, string(d.cfg.SecretKey), "") - // Build the HTTP client from the provided HTTPClientConfig. httpClient, err := config.NewClientFromConfig(d.cfg.HTTPClientConfig, "lightsail_sd") if err != nil { return nil, err } - // Build the AWS config with the provided region and credentials. - cfg, err := awsConfig.LoadDefaultConfig( - ctx, + // Build the AWS config with the provided region. + configOptions := []func(*awsConfig.LoadOptions) error{ awsConfig.WithRegion(d.cfg.Region), - awsConfig.WithCredentialsProvider(credProvider), - awsConfig.WithSharedConfigProfile(d.cfg.Profile), awsConfig.WithHTTPClient(httpClient), - ) + } + + // Only set static credentials if both access key and secret key are provided. + // Otherwise, let the AWS SDK use its default credential chain (environment variables, IAM role, etc.). + if d.cfg.AccessKey != "" && d.cfg.SecretKey != "" { + credProvider := credentials.NewStaticCredentialsProvider(d.cfg.AccessKey, string(d.cfg.SecretKey), "") + configOptions = append(configOptions, awsConfig.WithCredentialsProvider(credProvider)) + } + + // Set the profile if provided. + if d.cfg.Profile != "" { + configOptions = append(configOptions, awsConfig.WithSharedConfigProfile(d.cfg.Profile)) + } + + cfg, err := awsConfig.LoadDefaultConfig(ctx, configOptions...) if err != nil { return nil, fmt.Errorf("could not create aws config: %w", err) } diff --git a/go.mod b/go.mod index 2758e01f1d..e94a74bd49 100644 --- a/go.mod +++ b/go.mod @@ -114,7 +114,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect diff --git a/model/relabel/relabel.go b/model/relabel/relabel.go index c7c5439d54..c15049b2b0 100644 --- a/model/relabel/relabel.go +++ b/model/relabel/relabel.go @@ -145,7 +145,13 @@ func (c *Config) Validate(nameValidationScheme model.ValidationScheme) error { // UTF-8 allows ${} characters, so standard validation allow $variables by default. // TODO(bwplotka): Relabelling users cannot put $ and ${<...>} characters in metric names or values. // Design escaping mechanism to allow that, once valid use case appears. - return c.NameValidationScheme.IsValidLabelName(value) + switch c.NameValidationScheme { + case model.UTF8Validation: + return c.NameValidationScheme.IsValidLabelName(value) + default: + // For legacy validation, use the legacy regex that allows $variables. + return relabelTargetLegacy.MatchString(value) + } } if c.Action == Replace && varInRegexTemplate(c.TargetLabel) && !isValidLabelNameWithRegexVarFn(c.TargetLabel) { return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action) diff --git a/model/relabel/relabel_test.go b/model/relabel/relabel_test.go index 79730055cb..99a4e09f56 100644 --- a/model/relabel/relabel_test.go +++ b/model/relabel/relabel_test.go @@ -831,6 +831,22 @@ func TestRelabelValidate(t *testing.T) { NameValidationScheme: model.UTF8Validation, }, }, + { + config: Config{ + Regex: MustNewRegexp("__meta_kubernetes_pod_label_(strimzi_io_.+)"), + Action: LabelMap, + Replacement: "$1", + NameValidationScheme: model.LegacyValidation, + }, + }, + { + config: Config{ + Regex: MustNewRegexp("__meta_(.+)"), + Action: LabelMap, + Replacement: "${1}", + NameValidationScheme: model.LegacyValidation, + }, + }, } for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index 6144afa70d..e0996503fd 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -1,7 +1,7 @@ { "name": "@prometheus-io/mantine-ui", "private": true, - "version": "0.307.1", + "version": "0.307.2", "type": "module", "scripts": { "start": "vite", @@ -28,7 +28,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.307.1", + "@prometheus-io/codemirror-promql": "0.307.2", "@reduxjs/toolkit": "^2.9.0", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.2", diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index 3c8f6fd58c..f3da54efc9 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.307.1", + "version": "0.307.2", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.307.1", + "@prometheus-io/lezer-promql": "0.307.2", "lru-cache": "^11.2.2" }, "devDependencies": { diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index 951955cd53..93a4026630 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.307.1", + "version": "0.307.2", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 6eafc4f156..4c83492629 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "prometheus-io", - "version": "0.307.1", + "version": "0.307.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prometheus-io", - "version": "0.307.1", + "version": "0.307.2", "workspaces": [ "mantine-ui", "module/*" @@ -24,7 +24,7 @@ }, "mantine-ui": { "name": "@prometheus-io/mantine-ui", - "version": "0.307.1", + "version": "0.307.2", "dependencies": { "@codemirror/autocomplete": "^6.19.0", "@codemirror/language": "^6.11.3", @@ -42,7 +42,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.307.1", + "@prometheus-io/codemirror-promql": "0.307.2", "@reduxjs/toolkit": "^2.9.0", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.2", @@ -87,10 +87,10 @@ }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.307.1", + "version": "0.307.2", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.307.1", + "@prometheus-io/lezer-promql": "0.307.2", "lru-cache": "^11.2.2" }, "devDependencies": { @@ -120,7 +120,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.307.1", + "version": "0.307.2", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.8.0", diff --git a/web/ui/package.json b/web/ui/package.json index be701b3577..fb77e73485 100644 --- a/web/ui/package.json +++ b/web/ui/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-io", "description": "Monorepo for the Prometheus UI", - "version": "0.307.1", + "version": "0.307.2", "private": true, "scripts": { "build": "bash build_ui.sh --all",