Merge pull request #16080 from prometheus/owilliams/escapeconfig-00-cleanup

utf8: Remove support for legacy global validation setting
This commit is contained in:
Owen Williams 2025-03-13 14:21:09 -04:00 committed by GitHub
commit 0bfbd462ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 39 additions and 188 deletions

View File

@ -140,8 +140,9 @@ var (
) )
func init() { func init() {
// This can be removed when the default validation scheme in common is updated. // This can be removed when the legacy global mode is fully deprecated.
model.NameValidationScheme = model.UTF8Validation model.NameValidationScheme = model.UTF8Validation
prometheus.MustRegister(versioncollector.NewCollector(strings.ReplaceAll(appName, "-", "_"))) prometheus.MustRegister(versioncollector.NewCollector(strings.ReplaceAll(appName, "-", "_")))
var err error var err error

View File

@ -44,7 +44,7 @@ import (
) )
func init() { func init() {
// This can be removed when the default validation scheme in common is updated. // This can be removed when the legacy global mode is fully deprecated.
model.NameValidationScheme = model.UTF8Validation model.NameValidationScheme = model.UTF8Validation
} }

View File

@ -63,7 +63,7 @@ import (
) )
func init() { func init() {
// This can be removed when the default validation scheme in common is updated. // This can be removed when the legacy global mode is fully deprecated.
model.NameValidationScheme = model.UTF8Validation model.NameValidationScheme = model.UTF8Validation
} }

View File

@ -40,7 +40,7 @@ import (
) )
func init() { func init() {
// This can be removed when the default validation scheme in common is updated. // This can be removed when the legacy global mode is fully deprecated.
model.NameValidationScheme = model.UTF8Validation model.NameValidationScheme = model.UTF8Validation
} }

View File

@ -837,12 +837,11 @@ func (c *ScrapeConfig) Validate(globalConfig GlobalConfig) error {
} }
} }
switch globalConfig.MetricNameValidationScheme {
case LegacyValidationConfig:
case "", UTF8ValidationConfig:
if model.NameValidationScheme != model.UTF8Validation { if model.NameValidationScheme != model.UTF8Validation {
panic("utf8 name validation requested but model.NameValidationScheme is not set to UTF8") return errors.New("model.NameValidationScheme must be set to UTF8")
} }
switch globalConfig.MetricNameValidationScheme {
case "", LegacyValidationConfig, UTF8ValidationConfig:
default: default:
return fmt.Errorf("unknown name validation method specified, must be either 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme) return fmt.Errorf("unknown name validation method specified, must be either 'legacy' or 'utf8', got %s", globalConfig.MetricNameValidationScheme)
} }

View File

@ -15,7 +15,6 @@ package config
import ( import (
"crypto/tls" "crypto/tls"
"encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"os" "os"
@ -62,11 +61,6 @@ import (
"github.com/prometheus/prometheus/util/testutil" "github.com/prometheus/prometheus/util/testutil"
) )
func init() {
// This can be removed when the default validation scheme in common is updated.
model.NameValidationScheme = model.UTF8Validation
}
func mustParseURL(u string) *config.URL { func mustParseURL(u string) *config.URL {
parsed, err := url.Parse(u) parsed, err := url.Parse(u)
if err != nil { if err != nil {
@ -1716,11 +1710,7 @@ var expectedErrors = []struct {
}, },
{ {
filename: "labelname.bad.yml", filename: "labelname.bad.yml",
errMsg: `"not$allowed" is not a valid label name`, errMsg: `"\xff" is not a valid label name`,
},
{
filename: "labelname2.bad.yml",
errMsg: `"not:allowed" is not a valid label name`,
}, },
{ {
filename: "labelvalue.bad.yml", filename: "labelvalue.bad.yml",
@ -1792,16 +1782,12 @@ var expectedErrors = []struct {
}, },
{ {
filename: "labelmap.bad.yml", filename: "labelmap.bad.yml",
errMsg: "\"l-$1\" is invalid 'replacement' for labelmap action", errMsg: "!!binary value contains invalid base64 data",
}, },
{ {
filename: "lowercase.bad.yml", filename: "lowercase.bad.yml",
errMsg: "relabel configuration for lowercase action requires 'target_label' value", errMsg: "relabel configuration for lowercase action requires 'target_label' value",
}, },
{
filename: "lowercase2.bad.yml",
errMsg: "\"42lab\" is invalid 'target_label' for lowercase action",
},
{ {
filename: "lowercase3.bad.yml", filename: "lowercase3.bad.yml",
errMsg: "'replacement' can not be set for lowercase action", errMsg: "'replacement' can not be set for lowercase action",
@ -1810,10 +1796,6 @@ var expectedErrors = []struct {
filename: "uppercase.bad.yml", filename: "uppercase.bad.yml",
errMsg: "relabel configuration for uppercase action requires 'target_label' value", errMsg: "relabel configuration for uppercase action requires 'target_label' value",
}, },
{
filename: "uppercase2.bad.yml",
errMsg: "\"42lab\" is invalid 'target_label' for uppercase action",
},
{ {
filename: "uppercase3.bad.yml", filename: "uppercase3.bad.yml",
errMsg: "'replacement' can not be set for uppercase action", errMsg: "'replacement' can not be set for uppercase action",
@ -2181,10 +2163,6 @@ var expectedErrors = []struct {
} }
func TestBadConfigs(t *testing.T) { func TestBadConfigs(t *testing.T) {
model.NameValidationScheme = model.LegacyValidation
defer func() {
model.NameValidationScheme = model.UTF8Validation
}()
for _, ee := range expectedErrors { for _, ee := range expectedErrors {
_, err := LoadFile("testdata/"+ee.filename, false, promslog.NewNopLogger()) _, err := LoadFile("testdata/"+ee.filename, false, promslog.NewNopLogger())
require.ErrorContains(t, err, ee.errMsg, require.ErrorContains(t, err, ee.errMsg,
@ -2192,23 +2170,7 @@ func TestBadConfigs(t *testing.T) {
} }
} }
func TestBadStaticConfigsJSON(t *testing.T) {
model.NameValidationScheme = model.LegacyValidation
defer func() {
model.NameValidationScheme = model.UTF8Validation
}()
content, err := os.ReadFile("testdata/static_config.bad.json")
require.NoError(t, err)
var tg targetgroup.Group
err = json.Unmarshal(content, &tg)
require.Error(t, err)
}
func TestBadStaticConfigsYML(t *testing.T) { func TestBadStaticConfigsYML(t *testing.T) {
model.NameValidationScheme = model.LegacyValidation
defer func() {
model.NameValidationScheme = model.UTF8Validation
}()
content, err := os.ReadFile("testdata/static_config.bad.yml") content, err := os.ReadFile("testdata/static_config.bad.yml")
require.NoError(t, err) require.NoError(t, err)
var tg targetgroup.Group var tg targetgroup.Group
@ -2453,11 +2415,6 @@ func TestScrapeConfigDisableCompression(t *testing.T) {
} }
func TestScrapeConfigNameValidationSettings(t *testing.T) { func TestScrapeConfigNameValidationSettings(t *testing.T) {
model.NameValidationScheme = model.UTF8Validation
defer func() {
model.NameValidationScheme = model.LegacyValidation
}()
tests := []struct { tests := []struct {
name string name string
inputFile string inputFile string

View File

@ -2,4 +2,4 @@ scrape_configs:
- job_name: prometheus - job_name: prometheus
relabel_configs: relabel_configs:
- action: labelmap - action: labelmap
replacement: l-$1 replacement: !!binary "/w==$1"

View File

@ -1,3 +1,3 @@
global: global:
external_labels: external_labels:
not$allowed: value !!binary "/w==": value

View File

@ -1,3 +0,0 @@
global:
external_labels:
'not:allowed': value

View File

@ -1,6 +0,0 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- action: lowercase
source_labels: [__name__]
target_label: 42lab

View File

@ -1,7 +0,0 @@
{
"targets": ["1.2.3.4:9100"],
"labels": {
"some_valid_label": "foo",
"oops:this-label-is-invalid": "bar"
}
}

View File

@ -1,4 +1,4 @@
targets: ['1.2.3.4:9001', '1.2.3.5:9090'] targets: ['1.2.3.4:9001', '1.2.3.5:9090']
labels: labels:
valid_label: foo valid_label: foo
not:valid_label: bar !!binary "/w==": bar

View File

@ -1,6 +0,0 @@
scrape_configs:
- job_name: prometheus
relabel_configs:
- action: uppercase
source_labels: [__name__]
target_label: 42lab

View File

@ -104,14 +104,14 @@ func (ls Labels) IsValid(validationScheme model.ValidationScheme) bool {
if l.Name == model.MetricNameLabel { if l.Name == model.MetricNameLabel {
// If the default validation scheme has been overridden with legacy mode, // If the default validation scheme has been overridden with legacy mode,
// we need to call the special legacy validation checker. // we need to call the special legacy validation checker.
if validationScheme == model.LegacyValidation && model.NameValidationScheme == model.UTF8Validation && !model.IsValidLegacyMetricName(string(model.LabelValue(l.Value))) { if validationScheme == model.LegacyValidation && !model.IsValidLegacyMetricName(string(model.LabelValue(l.Value))) {
return strconv.ErrSyntax return strconv.ErrSyntax
} }
if !model.IsValidMetricName(model.LabelValue(l.Value)) { if !model.IsValidMetricName(model.LabelValue(l.Value)) {
return strconv.ErrSyntax return strconv.ErrSyntax
} }
} }
if validationScheme == model.LegacyValidation && model.NameValidationScheme == model.UTF8Validation { if validationScheme == model.LegacyValidation {
if !model.LabelName(l.Name).IsValidLegacy() || !model.LabelValue(l.Value).IsValid() { if !model.LabelName(l.Name).IsValidLegacy() || !model.LabelValue(l.Value).IsValid() {
return strconv.ErrSyntax return strconv.ErrSyntax
} }

View File

@ -285,7 +285,6 @@ func TestLabels_IsValid(t *testing.T) {
func TestLabels_ValidationModes(t *testing.T) { func TestLabels_ValidationModes(t *testing.T) {
for _, test := range []struct { for _, test := range []struct {
input Labels input Labels
globalMode model.ValidationScheme
callMode model.ValidationScheme callMode model.ValidationScheme
expected bool expected bool
}{ }{
@ -295,7 +294,6 @@ func TestLabels_ValidationModes(t *testing.T) {
"hostname", "localhost", "hostname", "localhost",
"job", "check", "job", "check",
), ),
globalMode: model.UTF8Validation,
callMode: model.UTF8Validation, callMode: model.UTF8Validation,
expected: true, expected: true,
}, },
@ -305,39 +303,15 @@ func TestLabels_ValidationModes(t *testing.T) {
"\xc5 bad utf8", "localhost", "\xc5 bad utf8", "localhost",
"job", "check", "job", "check",
), ),
globalMode: model.UTF8Validation,
callMode: model.UTF8Validation, callMode: model.UTF8Validation,
expected: false, expected: false,
}, },
{
// Setting the common model to legacy validation and then trying to check for UTF-8 on a
// per-call basis is not supported.
input: FromStrings(
"__name__", "test.utf8.metric",
"hostname", "localhost",
"job", "check",
),
globalMode: model.LegacyValidation,
callMode: model.UTF8Validation,
expected: false,
},
{
input: FromStrings(
"__name__", "test",
"hostname", "localhost",
"job", "check",
),
globalMode: model.LegacyValidation,
callMode: model.LegacyValidation,
expected: true,
},
{ {
input: FromStrings( input: FromStrings(
"__name__", "test.utf8.metric", "__name__", "test.utf8.metric",
"hostname", "localhost", "hostname", "localhost",
"job", "check", "job", "check",
), ),
globalMode: model.UTF8Validation,
callMode: model.LegacyValidation, callMode: model.LegacyValidation,
expected: false, expected: false,
}, },
@ -347,12 +321,10 @@ func TestLabels_ValidationModes(t *testing.T) {
"host.name", "localhost", "host.name", "localhost",
"job", "check", "job", "check",
), ),
globalMode: model.UTF8Validation,
callMode: model.LegacyValidation, callMode: model.LegacyValidation,
expected: false, expected: false,
}, },
} { } {
model.NameValidationScheme = test.globalMode
require.Equal(t, test.expected, test.input.IsValid(test.callMode)) require.Equal(t, test.expected, test.input.IsValid(test.callMode))
} }
} }

View File

@ -135,11 +135,6 @@ func (c *Config) Validate() error {
// Design escaping mechanism to allow that, once valid use case appears. // Design escaping mechanism to allow that, once valid use case appears.
return model.LabelName(value).IsValid() return model.LabelName(value).IsValid()
} }
if model.NameValidationScheme == model.LegacyValidation {
isValidLabelNameWithRegexVarFn = func(value string) bool {
return relabelTargetLegacy.MatchString(value)
}
}
if c.Action == Replace && varInRegexTemplate(c.TargetLabel) && !isValidLabelNameWithRegexVarFn(c.TargetLabel) { 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) return fmt.Errorf("%q is invalid 'target_label' for %s action", c.TargetLabel, c.Action)
} }

View File

@ -469,12 +469,6 @@ foobar{quantile="0.99"} 150.1`
} }
func TestUTF8OpenMetricsParse(t *testing.T) { func TestUTF8OpenMetricsParse(t *testing.T) {
oldValidationScheme := model.NameValidationScheme
model.NameValidationScheme = model.UTF8Validation
defer func() {
model.NameValidationScheme = oldValidationScheme
}()
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations. input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
# TYPE "go.gc_duration_seconds" summary # TYPE "go.gc_duration_seconds" summary
# UNIT "go.gc_duration_seconds" seconds # UNIT "go.gc_duration_seconds" seconds

View File

@ -205,12 +205,6 @@ testmetric{le="10"} 1`
} }
func TestUTF8PromParse(t *testing.T) { func TestUTF8PromParse(t *testing.T) {
oldValidationScheme := model.NameValidationScheme
model.NameValidationScheme = model.UTF8Validation
defer func() {
model.NameValidationScheme = oldValidationScheme
}()
input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations. input := `# HELP "go.gc_duration_seconds" A summary of the GC invocation durations.
# TYPE "go.gc_duration_seconds" summary # TYPE "go.gc_duration_seconds" summary
{"go.gc_duration_seconds",quantile="0"} 4.9351e-05 {"go.gc_duration_seconds",quantile="0"} 4.9351e-05

View File

@ -3970,7 +3970,6 @@ func TestParseExpressions(t *testing.T) {
EnableExperimentalFunctions = false EnableExperimentalFunctions = false
}) })
model.NameValidationScheme = model.UTF8Validation
for _, test := range testExpr { for _, test := range testExpr {
t.Run(readable(test.input), func(t *testing.T) { t.Run(readable(test.input), func(t *testing.T) {
expr, err := ParseExpr(test.input) expr, err := ParseExpr(test.input)

View File

@ -16,7 +16,6 @@ package parser
import ( import (
"testing" "testing"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/labels"
@ -170,8 +169,6 @@ func TestExprString(t *testing.T) {
}, },
} }
model.NameValidationScheme = model.UTF8Validation
for _, test := range inputs { for _, test := range inputs {
expr, err := ParseExpr(test.in) expr, err := ParseExpr(test.in)
require.NoError(t, err) require.NoError(t, err)

View File

@ -57,10 +57,6 @@ const (
DefaultMaxSamplesPerQuery = 10000 DefaultMaxSamplesPerQuery = 10000
) )
func init() {
model.NameValidationScheme = model.UTF8Validation
}
type TBRun interface { type TBRun interface {
testing.TB testing.TB
Run(string, func(*testing.T)) bool Run(string, func(*testing.T)) bool

View File

@ -56,11 +56,6 @@ import (
"github.com/prometheus/prometheus/util/testutil" "github.com/prometheus/prometheus/util/testutil"
) )
func init() {
// This can be removed when the default validation scheme in common is updated.
model.NameValidationScheme = model.UTF8Validation
}
func TestPopulateLabels(t *testing.T) { func TestPopulateLabels(t *testing.T) {
cases := []struct { cases := []struct {
in model.LabelSet in model.LabelSet

View File

@ -1325,14 +1325,13 @@ func TestScrapeLoopSeriesAdded(t *testing.T) {
} }
func TestScrapeLoopFailWithInvalidLabelsAfterRelabel(t *testing.T) { func TestScrapeLoopFailWithInvalidLabelsAfterRelabel(t *testing.T) {
model.NameValidationScheme = model.LegacyValidation
s := teststorage.New(t) s := teststorage.New(t)
defer s.Close() defer s.Close()
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
target := &Target{ target := &Target{
labels: labels.FromStrings("pod_label_invalid_012", "test"), labels: labels.FromStrings("pod_label_invalid_012\xff", "test"),
} }
relabelConfig := []*relabel.Config{{ relabelConfig := []*relabel.Config{{
Action: relabel.LabelMap, Action: relabel.LabelMap,
@ -1357,10 +1356,6 @@ func TestScrapeLoopFailWithInvalidLabelsAfterRelabel(t *testing.T) {
func TestScrapeLoopFailLegacyUnderUTF8(t *testing.T) { func TestScrapeLoopFailLegacyUnderUTF8(t *testing.T) {
// Test that scrapes fail when default validation is utf8 but scrape config is // Test that scrapes fail when default validation is utf8 but scrape config is
// legacy. // legacy.
model.NameValidationScheme = model.UTF8Validation
defer func() {
model.NameValidationScheme = model.LegacyValidation
}()
s := teststorage.New(t) s := teststorage.New(t)
defer s.Close() defer s.Close()
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@ -3711,8 +3706,6 @@ func TestScrapeReportLimit(t *testing.T) {
func TestScrapeUTF8(t *testing.T) { func TestScrapeUTF8(t *testing.T) {
s := teststorage.New(t) s := teststorage.New(t)
defer s.Close() defer s.Close()
model.NameValidationScheme = model.UTF8Validation
t.Cleanup(func() { model.NameValidationScheme = model.LegacyValidation })
cfg := &config.ScrapeConfig{ cfg := &config.ScrapeConfig{
JobName: "test", JobName: "test",

View File

@ -165,11 +165,6 @@ func TestWriteV2RequestFixture(t *testing.T) {
} }
func TestValidateLabelsAndMetricName(t *testing.T) { func TestValidateLabelsAndMetricName(t *testing.T) {
oldScheme := model.NameValidationScheme
model.NameValidationScheme = model.LegacyValidation
defer func() {
model.NameValidationScheme = oldScheme
}()
tests := []struct { tests := []struct {
input []prompb.Label input []prompb.Label
expectedErr string expectedErr string
@ -194,18 +189,10 @@ func TestValidateLabelsAndMetricName(t *testing.T) {
{ {
input: []prompb.Label{ input: []prompb.Label{
{Name: "__name__", Value: "name"}, {Name: "__name__", Value: "name"},
{Name: "@labelName", Value: "labelValue"}, {Name: "@labelName\xff", Value: "labelValue"},
}, },
expectedErr: "invalid label name: @labelName", expectedErr: "invalid label name: @labelName\xff",
description: "label name with @", description: "label name with \xff",
},
{
input: []prompb.Label{
{Name: "__name__", Value: "name"},
{Name: "123labelName", Value: "labelValue"},
},
expectedErr: "invalid label name: 123labelName",
description: "label name starts with numbers",
}, },
{ {
input: []prompb.Label{ input: []prompb.Label{
@ -225,10 +212,10 @@ func TestValidateLabelsAndMetricName(t *testing.T) {
}, },
{ {
input: []prompb.Label{ input: []prompb.Label{
{Name: "__name__", Value: "@invalid_name"}, {Name: "__name__", Value: "invalid_name\xff"},
}, },
expectedErr: "invalid metric name: @invalid_name", expectedErr: "invalid metric name: invalid_name\xff",
description: "metric name starts with @", description: "metric name has invalid utf8",
}, },
{ {
input: []prompb.Label{ input: []prompb.Label{

View File

@ -251,7 +251,7 @@ func (h *writeHandler) write(ctx context.Context, req *prompb.WriteRequest) (err
// TODO(bwplotka): Even as per 1.0 spec, this should be a 400 error, while other samples are // TODO(bwplotka): Even as per 1.0 spec, this should be a 400 error, while other samples are
// potentially written. Perhaps unify with fixed writeV2 implementation a bit. // potentially written. Perhaps unify with fixed writeV2 implementation a bit.
if !ls.Has(labels.MetricName) || !ls.IsValid(model.NameValidationScheme) { if !ls.Has(labels.MetricName) || !ls.IsValid(model.UTF8Validation) {
h.logger.Warn("Invalid metric names or labels", "got", ls.String()) h.logger.Warn("Invalid metric names or labels", "got", ls.String())
samplesWithInvalidLabels++ samplesWithInvalidLabels++
continue continue
@ -392,7 +392,7 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs *
// Validate series labels early. // Validate series labels early.
// NOTE(bwplotka): While spec allows UTF-8, Prometheus Receiver may impose // NOTE(bwplotka): While spec allows UTF-8, Prometheus Receiver may impose
// specific limits and follow https://prometheus.io/docs/specs/remote_write_spec_2_0/#invalid-samples case. // specific limits and follow https://prometheus.io/docs/specs/remote_write_spec_2_0/#invalid-samples case.
if !ls.Has(labels.MetricName) || !ls.IsValid(model.NameValidationScheme) { if !ls.Has(labels.MetricName) || !ls.IsValid(model.UTF8Validation) {
badRequestErrs = append(badRequestErrs, fmt.Errorf("invalid metric name or labels, got %v", ls.String())) badRequestErrs = append(badRequestErrs, fmt.Errorf("invalid metric name or labels, got %v", ls.String()))
samplesWithInvalidLabels += len(ts.Samples) + len(ts.Histograms) samplesWithInvalidLabels += len(ts.Samples) + len(ts.Histograms)
continue continue

View File

@ -1117,7 +1117,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
metadata []targetMetadata metadata []targetMetadata
exemplars []exemplar.QueryResult exemplars []exemplar.QueryResult
zeroFunc func(interface{}) zeroFunc func(interface{})
nameValidationScheme model.ValidationScheme
} }
rulesZeroFunc := func(i interface{}) { rulesZeroFunc := func(i interface{}) {
@ -3247,13 +3246,12 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
"boo", "boo",
}, },
}, },
// Bad name parameter for legacy validation. // Bad name parameter
{ {
endpoint: api.labelValues, endpoint: api.labelValues,
params: map[string]string{ params: map[string]string{
"name": "host.name", "name": "host.name\xff",
}, },
nameValidationScheme: model.LegacyValidation,
errType: errorBadData, errType: errorBadData,
}, },
// Valid utf8 name parameter for utf8 validation. // Valid utf8 name parameter for utf8 validation.
@ -3262,7 +3260,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
params: map[string]string{ params: map[string]string{
"name": "host.name", "name": "host.name",
}, },
nameValidationScheme: model.UTF8Validation,
response: []string{ response: []string{
"localhost", "localhost",
}, },
@ -3273,7 +3270,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
params: map[string]string{ params: map[string]string{
"name": "U__junk_0a__7b__7d__2c__3d_:_20__20_chars", "name": "U__junk_0a__7b__7d__2c__3d_:_20__20_chars",
}, },
nameValidationScheme: model.UTF8Validation,
response: []string{ response: []string{
"bar", "bar",
}, },
@ -3706,8 +3702,6 @@ func testEndpoints(t *testing.T, api *API, tr *testTargetRetriever, es storage.E
ctx = route.WithParam(ctx, p, v) ctx = route.WithParam(ctx, p, v)
} }
model.NameValidationScheme = test.nameValidationScheme
req, err := request(method, test.query) req, err := request(method, test.query)
require.NoError(t, err) require.NoError(t, err)