Skip to content

Commit

Permalink
fix: Validate metric key names (#4540)
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Behar <[email protected]>
  • Loading branch information
simster7 committed Nov 17, 2020
1 parent c469b05 commit a712e53
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
28 changes: 25 additions & 3 deletions workflow/metrics/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

var (
invalidMetricNameError = "metric name is invalid: names may only contain alphanumeric characters, '_', or ':'"
invalidMetricLabelrror = "metric label '%s' is invalid: keys may only contain alphanumeric characters, '_', or ':'"
descRegex = regexp.MustCompile(fmt.Sprintf(`Desc{fqName: "%s_%s_(.+?)", help: "(.+?)", constLabels: {`, argoNamespace, workflowsSubsystem))
)

Expand Down Expand Up @@ -56,7 +57,11 @@ func ConstructRealTimeGaugeMetric(metricSpec *wfv1.Prometheus, valueFunc func()

func constructOrUpdateCounterMetric(metric prometheus.Metric, metricSpec *wfv1.Prometheus) (prometheus.Metric, error) {
if metric == nil {
metric = newCounter(metricSpec.Name, metricSpec.Help, metricSpec.GetMetricLabels())
labels := metricSpec.GetMetricLabels()
if err := ValidateMetricLabels(labels); err != nil {
return nil, err
}
metric = newCounter(metricSpec.Name, metricSpec.Help, labels)
}

val, err := strconv.ParseFloat(metricSpec.Counter.Value, 64)
Expand All @@ -71,7 +76,11 @@ func constructOrUpdateCounterMetric(metric prometheus.Metric, metricSpec *wfv1.P

func constructOrUpdateGaugeMetric(metric prometheus.Metric, metricSpec *wfv1.Prometheus) (prometheus.Metric, error) {
if metric == nil {
metric = newGauge(metricSpec.Name, metricSpec.Help, metricSpec.GetMetricLabels())
labels := metricSpec.GetMetricLabels()
if err := ValidateMetricLabels(labels); err != nil {
return nil, err
}
metric = newGauge(metricSpec.Name, metricSpec.Help, labels)
}

val, err := strconv.ParseFloat(metricSpec.Gauge.Value, 64)
Expand All @@ -86,7 +95,11 @@ func constructOrUpdateGaugeMetric(metric prometheus.Metric, metricSpec *wfv1.Pro

func constructOrUpdateHistogramMetric(metric prometheus.Metric, metricSpec *wfv1.Prometheus) (prometheus.Metric, error) {
if metric == nil {
metric = newHistogram(metricSpec.Name, metricSpec.Help, metricSpec.GetMetricLabels(), metricSpec.Histogram.GetBuckets())
labels := metricSpec.GetMetricLabels()
if err := ValidateMetricLabels(labels); err != nil {
return nil, err
}
metric = newHistogram(metricSpec.Name, metricSpec.Help, labels, metricSpec.Histogram.GetBuckets())
}

val, err := strconv.ParseFloat(metricSpec.Histogram.Value, 64)
Expand Down Expand Up @@ -179,6 +192,15 @@ func IsValidMetricName(name string) bool {
return model.IsValidMetricName(model.LabelValue(name))
}

func ValidateMetricLabels(metrics map[string]string) error {
for name := range metrics {
if !IsValidMetricName(name) {
return fmt.Errorf(invalidMetricLabelrror, name)
}
}
return nil
}

func mustBeRecoverable(name, help string, metric prometheus.Metric) {
recoveredName, recoveredHelp := recoverMetricNameAndHelpFromDesc(metric.Desc().String())
if name != recoveredName {
Expand Down
3 changes: 3 additions & 0 deletions workflow/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ func (ctx *templateValidationCtx) validateTemplate(tmpl *wfv1.Template, tmplCtx
if !metrics.IsValidMetricName(metric.Name) {
return errors.Errorf(errors.CodeBadRequest, "templates.%s metric name '%s' is invalid. Metric names must contain alphanumeric characters, '_', or ':'", tmpl.Name, metric.Name)
}
if err := metrics.ValidateMetricLabels(metric.GetMetricLabels()); err != nil {
return err
}
if metric.Help == "" {
return errors.Errorf(errors.CodeBadRequest, "templates.%s metric '%s' must contain a help string under 'help: ' field", tmpl.Name, metric.Name)
}
Expand Down
27 changes: 27 additions & 0 deletions workflow/validate/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2318,6 +2318,33 @@ func TestInvalidMetricName(t *testing.T) {
assert.EqualError(t, err, "templates.whalesay metric name 'invalid.metric.name' is invalid. Metric names must contain alphanumeric characters, '_', or ':'")
}

var invalidMetricLabelName = `
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: hello-world-
spec:
entrypoint: whalesay
templates:
- name: whalesay
metrics:
prometheus:
- name: valid
help: "invalid"
labels:
- key: invalid.key
value: hi
gauge:
value: 1
container:
image: docker/whalesay:latest
`

func TestInvalidMetricLabelName(t *testing.T) {
_, err := validate(invalidMetricLabelName)
assert.EqualError(t, err, "metric label 'invalid.key' is invalid: keys may only contain alphanumeric characters, '_', or ':'")
}

var invalidMetricHelp = `
apiVersion: argoproj.io/v1alpha1
kind: Workflow
Expand Down

0 comments on commit a712e53

Please sign in to comment.