Check target labels are valid. Check for address after relabelling.

Fixes #2822
Fixes #2819
This commit is contained in:
Brian Brazil 2017-06-09 16:18:19 +01:00
parent bfa37c8ee3
commit d8b4995ddd
2 changed files with 95 additions and 12 deletions

View File

@ -266,9 +266,6 @@ func (app *countingAppender) Append(s *model.Sample) error {
// Returns a nil label set if the target is dropped during relabeling. // Returns a nil label set if the target is dropped during relabeling.
func populateLabels(lset model.LabelSet, cfg *config.ScrapeConfig) (res, orig model.LabelSet, err error) { func populateLabels(lset model.LabelSet, cfg *config.ScrapeConfig) (res, orig model.LabelSet, err error) {
lset = lset.Clone() lset = lset.Clone()
if _, ok := lset[model.AddressLabel]; !ok {
return nil, nil, fmt.Errorf("no address")
}
// Copy labels into the labelset for the target if they are not // Copy labels into the labelset for the target if they are not
// set already. Apply the labelsets in order of decreasing precedence. // set already. Apply the labelsets in order of decreasing precedence.
scrapeLabels := model.LabelSet{ scrapeLabels := model.LabelSet{
@ -295,6 +292,9 @@ func populateLabels(lset model.LabelSet, cfg *config.ScrapeConfig) (res, orig mo
if lset == nil { if lset == nil {
return nil, nil, nil return nil, nil, nil
} }
if _, ok := lset[model.AddressLabel]; !ok {
return nil, nil, fmt.Errorf("no address")
}
// addPort checks whether we should add a default port to the address. // addPort checks whether we should add a default port to the address.
// If the address is not valid, we don't append a port either. // If the address is not valid, we don't append a port either.
@ -327,9 +327,14 @@ func populateLabels(lset model.LabelSet, cfg *config.ScrapeConfig) (res, orig mo
// Meta labels are deleted after relabelling. Other internal labels propagate to // Meta labels are deleted after relabelling. Other internal labels propagate to
// the target which decides whether they will be part of their label set. // the target which decides whether they will be part of their label set.
for ln := range lset { for ln, lv := range lset {
if strings.HasPrefix(string(ln), model.MetaLabelPrefix) { if strings.HasPrefix(string(ln), model.MetaLabelPrefix) {
delete(lset, ln) delete(lset, ln)
continue
}
// Check label values are valid, drop the target if not.
if !lv.IsValid() {
return nil, nil, fmt.Errorf("invalid label value for %q: %q", ln, lv)
} }
} }

View File

@ -14,6 +14,7 @@
package retrieval package retrieval
import ( import (
"fmt"
"reflect" "reflect"
"testing" "testing"
@ -35,6 +36,7 @@ func TestPopulateLabels(t *testing.T) {
cfg *config.ScrapeConfig cfg *config.ScrapeConfig
res model.LabelSet res model.LabelSet
resOrig model.LabelSet resOrig model.LabelSet
err error
}{ }{
// Regular population of scrape config options. // Regular population of scrape config options.
{ {
@ -117,11 +119,24 @@ func TestPopulateLabels(t *testing.T) {
model.JobLabel: "job", model.JobLabel: "job",
}, },
}, },
// Apply relabeling. // Address label missing.
{ {
in: model.LabelSet{ in: model.LabelSet{
model.AddressLabel: "1.2.3.4:1000", "custom": "value",
"custom": "value", },
cfg: &config.ScrapeConfig{
Scheme: "https",
MetricsPath: "/metrics",
JobName: "job",
},
res: nil,
resOrig: nil,
err: fmt.Errorf("no address"),
},
// Address label missing, but added in relabelling.
{
in: model.LabelSet{
"custom": "host:1234",
}, },
cfg: &config.ScrapeConfig{ cfg: &config.ScrapeConfig{
Scheme: "https", Scheme: "https",
@ -129,21 +144,84 @@ func TestPopulateLabels(t *testing.T) {
JobName: "job", JobName: "job",
RelabelConfigs: []*config.RelabelConfig{ RelabelConfigs: []*config.RelabelConfig{
{ {
Action: config.RelabelDrop, Action: config.RelabelReplace,
Regex: mustNewRegexp(".*"), Regex: mustNewRegexp("(.*)"),
SourceLabels: model.LabelNames{"job"}, SourceLabels: model.LabelNames{"custom"},
Replacement: "${1}",
TargetLabel: string(model.AddressLabel),
}, },
}, },
}, },
res: model.LabelSet{
model.AddressLabel: "host:1234",
model.InstanceLabel: "host:1234",
model.SchemeLabel: "https",
model.MetricsPathLabel: "/metrics",
model.JobLabel: "job",
"custom": "host:1234",
},
resOrig: model.LabelSet{
model.SchemeLabel: "https",
model.MetricsPathLabel: "/metrics",
model.JobLabel: "job",
"custom": "host:1234",
},
},
// Address label missing, but added in relabelling.
{
in: model.LabelSet{
"custom": "host:1234",
},
cfg: &config.ScrapeConfig{
Scheme: "https",
MetricsPath: "/metrics",
JobName: "job",
RelabelConfigs: []*config.RelabelConfig{
{
Action: config.RelabelReplace,
Regex: mustNewRegexp("(.*)"),
SourceLabels: model.LabelNames{"custom"},
Replacement: "${1}",
TargetLabel: string(model.AddressLabel),
},
},
},
res: model.LabelSet{
model.AddressLabel: "host:1234",
model.InstanceLabel: "host:1234",
model.SchemeLabel: "https",
model.MetricsPathLabel: "/metrics",
model.JobLabel: "job",
"custom": "host:1234",
},
resOrig: model.LabelSet{
model.SchemeLabel: "https",
model.MetricsPathLabel: "/metrics",
model.JobLabel: "job",
"custom": "host:1234",
},
},
// Invalid UTF-8 in label.
{
in: model.LabelSet{
model.AddressLabel: "1.2.3.4:1000",
"custom": "\xbd",
},
cfg: &config.ScrapeConfig{
Scheme: "https",
MetricsPath: "/metrics",
JobName: "job",
},
res: nil, res: nil,
resOrig: nil, resOrig: nil,
err: fmt.Errorf("invalid label value for \"custom\": \"\\xbd\""),
}, },
} }
for i, c := range cases { for i, c := range cases {
in := c.in.Clone() in := c.in.Clone()
res, orig, err := populateLabels(c.in, c.cfg) res, orig, err := populateLabels(c.in, c.cfg)
if err != nil { if !reflect.DeepEqual(err, c.err) {
t.Fatalf("case %d: %s", i, err) t.Fatalf("case %d: wanted %v error, got %v", i, c.err, err)
} }
if !reflect.DeepEqual(c.in, in) { if !reflect.DeepEqual(c.in, in) {
t.Errorf("case %d: input lset was changed was\n\t%+v\n now\n\t%+v", i, in, c.in) t.Errorf("case %d: input lset was changed was\n\t%+v\n now\n\t%+v", i, in, c.in)