Consolidate Distributor template parsing
This commit is contained in:
@@ -1725,43 +1725,59 @@ func TestDistributorBatchTemplateRendering(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDistributorBatchTemplateRejectsUnknownAndMalformedVariables(t *testing.T) {
|
func TestDistributorTemplateRejectsUnknownVariables(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
template string
|
template string
|
||||||
|
render func(string) error
|
||||||
}{
|
}{
|
||||||
{name: "Unknown", template: "{report_id}"},
|
{
|
||||||
{name: "Unclosed", template: "{batch"},
|
name: "SingleReport",
|
||||||
{name: "Unopened", template: "batch}"},
|
template: "{unknown}",
|
||||||
{name: "Empty", template: "{}"},
|
render: func(template string) error {
|
||||||
|
_, err := RenderDistributorBundleID(template, DistributorTemplateValues{})
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Batch",
|
||||||
|
template: "{report_id}",
|
||||||
|
render: func(template string) error {
|
||||||
|
_, err := RenderDistributorBatchBundleID(template, DistributorBatchTemplateValues{})
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
_, err := RenderDistributorBatchBundleID(tt.template, DistributorBatchTemplateValues{})
|
err := tt.render(tt.template)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("RenderDistributorBatchBundleID() error = nil, want error")
|
t.Fatal("rendering error = nil, want error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDistributorTemplateRejectsUnknownAndMalformedVariables(t *testing.T) {
|
func TestDistributorTemplateParserRejectsMalformedVariables(t *testing.T) {
|
||||||
|
const name = "notify.distributor.bundle_id_template"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
template string
|
template string
|
||||||
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{name: "Unknown", template: "{unknown}"},
|
{name: "Unclosed", template: "{location_id", wantErr: name + " contains an unclosed template variable"},
|
||||||
{name: "Unclosed", template: "{location_id"},
|
{name: "Unopened", template: "location_id}", wantErr: name + " contains an unopened template variable"},
|
||||||
{name: "Unopened", template: "location_id}"},
|
{name: "Empty", template: "{}", wantErr: name + " contains an empty template variable"},
|
||||||
{name: "Empty", template: "{}"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
_, err := RenderDistributorBundleID(tt.template, DistributorTemplateValues{})
|
_, err := renderDistributorTemplate(name, tt.template, func(variable string) (string, bool) {
|
||||||
if err == nil {
|
return "value", variable == "location_id"
|
||||||
t.Fatal("RenderDistributorBundleID() error = nil, want error")
|
})
|
||||||
|
if err == nil || err.Error() != tt.wantErr {
|
||||||
|
t.Fatalf("error = %v, want %q", err, tt.wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ var distributorBatchIdempotencyTemplateVariables = map[string]struct{}{
|
|||||||
var distributorBatchPipelineTemplateVariables = distributorBatchTemplateVariables
|
var distributorBatchPipelineTemplateVariables = distributorBatchTemplateVariables
|
||||||
|
|
||||||
func RenderDistributorBundleID(template string, values DistributorTemplateValues) (string, error) {
|
func RenderDistributorBundleID(template string, values DistributorTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorTemplate("notify.distributor.bundle_id_template", template, values, distributorTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.bundle_id_template", template, newDistributorTemplateResolver(values, distributorTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func RenderDistributorBundleID(template string, values DistributorTemplateValues
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderDistributorPipelineID(template string, values DistributorTemplateValues) (string, error) {
|
func RenderDistributorPipelineID(template string, values DistributorTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorTemplate("notify.distributor.pipeline_id_template", template, values, distributorPipelineTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.pipeline_id_template", template, newDistributorTemplateResolver(values, distributorPipelineTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ func RenderDistributorPipelineID(template string, values DistributorTemplateValu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderDistributorIdempotencyKey(template string, values DistributorTemplateValues) (string, error) {
|
func RenderDistributorIdempotencyKey(template string, values DistributorTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorTemplate("notify.distributor.idempotency_key_template", template, values, distributorIdempotencyTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.idempotency_key_template", template, newDistributorTemplateResolver(values, distributorIdempotencyTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ func RenderDistributorIdempotencyKey(template string, values DistributorTemplate
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderDistributorBatchBundleID(template string, values DistributorBatchTemplateValues) (string, error) {
|
func RenderDistributorBatchBundleID(template string, values DistributorBatchTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorBatchTemplate("notify.distributor.batch.bundle_id_template", template, values, distributorBatchTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.batch.bundle_id_template", template, newDistributorBatchTemplateResolver(values, distributorBatchTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ func RenderDistributorBatchBundleID(template string, values DistributorBatchTemp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderDistributorBatchPipelineID(template string, values DistributorBatchTemplateValues) (string, error) {
|
func RenderDistributorBatchPipelineID(template string, values DistributorBatchTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorBatchTemplate("notify.distributor.batch.pipeline_id_template", template, values, distributorBatchPipelineTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.batch.pipeline_id_template", template, newDistributorBatchTemplateResolver(values, distributorBatchPipelineTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ func RenderDistributorBatchPipelineID(template string, values DistributorBatchTe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RenderDistributorBatchIdempotencyKey(template string, values DistributorBatchTemplateValues) (string, error) {
|
func RenderDistributorBatchIdempotencyKey(template string, values DistributorBatchTemplateValues) (string, error) {
|
||||||
rendered, err := renderDistributorBatchTemplate("notify.distributor.batch.idempotency_key_template", template, values, distributorBatchIdempotencyTemplateVariables)
|
rendered, err := renderDistributorTemplate("notify.distributor.batch.idempotency_key_template", template, newDistributorBatchTemplateResolver(values, distributorBatchIdempotencyTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ func RenderDistributorReportPaths(name string, templates []string, values Distri
|
|||||||
seen := make(map[string]struct{}, len(templates))
|
seen := make(map[string]struct{}, len(templates))
|
||||||
for i, template := range templates {
|
for i, template := range templates {
|
||||||
itemName := fmt.Sprintf("%s[%d]", name, i)
|
itemName := fmt.Sprintf("%s[%d]", name, i)
|
||||||
rendered, err := renderDistributorTemplate(itemName, template, values, distributorTemplateVariables)
|
rendered, err := renderDistributorTemplate(itemName, template, newDistributorTemplateResolver(values, distributorTemplateVariables))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -168,16 +168,18 @@ func RenderDistributorReportPaths(name string, templates []string, values Distri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateDistributorTemplate(name, template string, allowed map[string]struct{}) error {
|
func validateDistributorTemplate(name, template string, allowed map[string]struct{}) error {
|
||||||
_, err := renderDistributorTemplate(name, template, DistributorTemplateValues{}, allowed)
|
_, err := renderDistributorTemplate(name, template, newDistributorTemplateResolver(DistributorTemplateValues{}, allowed))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateDistributorBatchTemplate(name, template string, allowed map[string]struct{}) error {
|
func validateDistributorBatchTemplate(name, template string, allowed map[string]struct{}) error {
|
||||||
_, err := renderDistributorBatchTemplate(name, template, DistributorBatchTemplateValues{}, allowed)
|
_, err := renderDistributorTemplate(name, template, newDistributorBatchTemplateResolver(DistributorBatchTemplateValues{}, allowed))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderDistributorTemplate(name, template string, values DistributorTemplateValues, allowed map[string]struct{}) (string, error) {
|
type distributorTemplateResolver func(string) (string, bool)
|
||||||
|
|
||||||
|
func renderDistributorTemplate(name, template string, resolve distributorTemplateResolver) (string, error) {
|
||||||
var rendered strings.Builder
|
var rendered strings.Builder
|
||||||
for i := 0; i < len(template); {
|
for i := 0; i < len(template); {
|
||||||
switch template[i] {
|
switch template[i] {
|
||||||
@@ -190,10 +192,11 @@ func renderDistributorTemplate(name, template string, values DistributorTemplate
|
|||||||
if variable == "" {
|
if variable == "" {
|
||||||
return "", fmt.Errorf("%s contains an empty template variable", name)
|
return "", fmt.Errorf("%s contains an empty template variable", name)
|
||||||
}
|
}
|
||||||
if _, ok := allowed[variable]; !ok {
|
value, ok := resolve(variable)
|
||||||
|
if !ok {
|
||||||
return "", fmt.Errorf("%s contains unknown template variable %q", name, variable)
|
return "", fmt.Errorf("%s contains unknown template variable %q", name, variable)
|
||||||
}
|
}
|
||||||
rendered.WriteString(distributorTemplateValue(variable, values))
|
rendered.WriteString(value)
|
||||||
i += end + 2
|
i += end + 2
|
||||||
case '}':
|
case '}':
|
||||||
return "", fmt.Errorf("%s contains an unopened template variable", name)
|
return "", fmt.Errorf("%s contains an unopened template variable", name)
|
||||||
@@ -205,32 +208,22 @@ func renderDistributorTemplate(name, template string, values DistributorTemplate
|
|||||||
return rendered.String(), nil
|
return rendered.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderDistributorBatchTemplate(name, template string, values DistributorBatchTemplateValues, allowed map[string]struct{}) (string, error) {
|
func newDistributorTemplateResolver(values DistributorTemplateValues, allowed map[string]struct{}) distributorTemplateResolver {
|
||||||
var rendered strings.Builder
|
return func(variable string) (string, bool) {
|
||||||
for i := 0; i < len(template); {
|
if _, ok := allowed[variable]; !ok {
|
||||||
switch template[i] {
|
return "", false
|
||||||
case '{':
|
|
||||||
end := strings.IndexByte(template[i+1:], '}')
|
|
||||||
if end < 0 {
|
|
||||||
return "", fmt.Errorf("%s contains an unclosed template variable", name)
|
|
||||||
}
|
|
||||||
variable := template[i+1 : i+1+end]
|
|
||||||
if variable == "" {
|
|
||||||
return "", fmt.Errorf("%s contains an empty template variable", name)
|
|
||||||
}
|
|
||||||
if _, ok := allowed[variable]; !ok {
|
|
||||||
return "", fmt.Errorf("%s contains unknown template variable %q", name, variable)
|
|
||||||
}
|
|
||||||
rendered.WriteString(distributorBatchTemplateValue(variable, values))
|
|
||||||
i += end + 2
|
|
||||||
case '}':
|
|
||||||
return "", fmt.Errorf("%s contains an unopened template variable", name)
|
|
||||||
default:
|
|
||||||
rendered.WriteByte(template[i])
|
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
return distributorTemplateValue(variable, values), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDistributorBatchTemplateResolver(values DistributorBatchTemplateValues, allowed map[string]struct{}) distributorTemplateResolver {
|
||||||
|
return func(variable string) (string, bool) {
|
||||||
|
if _, ok := allowed[variable]; !ok {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return distributorBatchTemplateValue(variable, values), true
|
||||||
}
|
}
|
||||||
return rendered.String(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func distributorTemplateValue(variable string, values DistributorTemplateValues) string {
|
func distributorTemplateValue(variable string, values DistributorTemplateValues) string {
|
||||||
|
|||||||
Reference in New Issue
Block a user