Skip to content

Commit

Permalink
Workaround new line parsing issues in go-yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
prymitive committed Jun 17, 2021
1 parent bc93b7c commit 3cc8a75
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 4 deletions.
64 changes: 64 additions & 0 deletions cmd/pint/tests/0012_issue_20.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
pint.ok lint rules
! stdout .
cmp stderr stderr.txt

-- stderr.txt --
level=info msg="Loading configuration file" path=.pint.hcl
level=info msg="File parsed" path=rules/1.yaml rules=1
level=warn msg="Tried to read more lines than present in the source file, this is likely due to '\n' usage in some rules, see https://github.com/cloudflare/pint/issues/20 for details" path=rules/1.yaml
rules/1.yaml:9-13: runbook_url annotation is required (alerts/annotation)
annotations:
summary: "HAProxy server healthcheck failure (instance {{ $labels.instance }})"
description: "Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"

-- rules/1.yaml --
groups:
- name: "haproxy.api_server.rules"
rules:
- alert: HaproxyServerHealthcheckFailure
expr: increase(haproxy_server_check_failures_total[15m]) > 100
for: 5m
labels:
severity: 24x7
annotations:
summary: "HAProxy server healthcheck failure (instance {{ $labels.instance }})"
description: "Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
-- .pint.hcl --
rule {
match {
kind = "alerting"
}
# Each alert must have a 'severity' annotation that's either '24x7','10x5' or 'debug'.
label "severity" {
severity = "bug"
value = "(24x7|10x5|debug)"
required = true
}
annotation "runbook_url" {
severity = "warning"
required = true
}
}

rule {
# Disallow spaces in label/annotation keys, they're only allowed in values.
reject ".* +.*" {
label_keys = true
annotation_keys = true
}

# Disallow URLs in labels, they should go to annotations.
reject "https?://.+" {
label_keys = true
label_values = true
}
# Check how many times each alert would fire in the last 1d.
alerts {
range = "1d"
step = "1m"
resolve = "5m"
}
# Check if '{{ $value }}'/'{{ .Value }}' is used in labels
# https://www.robustperception.io/dont-put-the-value-in-alert-labels
value {}
}
2 changes: 1 addition & 1 deletion internal/parser/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type FilePosition struct {
Lines []int
}

func (fp FilePosition) FistLine() (line int) {
func (fp FilePosition) FirstLine() (line int) {
for _, l := range fp.Lines {
if line == 0 || l < line {
line = l
Expand Down
4 changes: 2 additions & 2 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ func parseRule(content []byte, node *yaml.Node) (rule Rule, isEmpty bool, err er
}
}

if exprPart != nil && exprPart.Key.Position.FistLine() != exprPart.Value.Position.FistLine() {
if exprPart != nil && exprPart.Key.Position.FirstLine() != exprPart.Value.Position.FirstLine() {
for {
start := exprPart.Value.Position.FistLine() - 1
start := exprPart.Value.Position.FirstLine() - 1
end := exprPart.Value.Position.LastLine()
input := strings.Join(strings.Split(string(content), "\n")[start:end], "")
input = strings.ReplaceAll(input, " ", "")
Expand Down
117 changes: 117 additions & 0 deletions internal/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,123 @@ data:
`),
output: nil,
},
/*
FIXME https://github.com/cloudflare/pint/issues/20
{
content: []byte(`groups:
- name: "haproxy.api_server.rules"
rules:
- alert: HaproxyServerHealthcheckFailure
expr: increase(haproxy_server_check_failures_total[15m]) > 100
for: 5m
labels:
severity: 24x7
annotations:
summary: "HAProxy server healthcheck failure (instance {{ $labels.instance }})"
description: "Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
`),
output: []parser.Rule{
{
AlertingRule: &parser.AlertingRule{
Alert: parser.YamlKeyValue{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{4}},
Value: "alert",
},
Value: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{4}},
Value: "HaproxyServerHealthcheckFailure",
},
},
Expr: parser.PromQLExpr{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{5}},
Value: "expr",
},
Value: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{5}},
Value: "increase(haproxy_server_check_failures_total[15m]) > 100",
},
Query: &parser.PromQLNode{
Expr: "increase(haproxy_server_check_failures_total[15m]) > 100",
Children: []*parser.PromQLNode{
{
Expr: "increase(haproxy_server_check_failures_total[15m])",
Children: []*parser.PromQLNode{
{
Expr: "haproxy_server_check_failures_total[15m]",
Children: []*parser.PromQLNode{
{
Expr: "haproxy_server_check_failures_total",
},
},
},
},
},
{Expr: "100"},
},
},
},
For: &parser.YamlKeyValue{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{6}},
Value: "for",
},
Value: &parser.YamlNode{Position: parser.FilePosition{Lines: []int{6}},
Value: "5m",
},
},
Labels: &parser.YamlMap{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{7}},
Value: "labels",
},
Items: []*parser.YamlKeyValue{
{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{8}},
Value: "severity",
},
Value: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{8}},
Value: "24x7",
},
},
},
},
Annotations: &parser.YamlMap{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{9}},
Value: "annotations",
},
Items: []*parser.YamlKeyValue{
{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{10}},
Value: "summary",
},
Value: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{10}},
Value: "HAProxy server healthcheck failure (instance {{ $labels.instance }})",
},
},
{
Key: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{11}},
Value: "description",
},
Value: &parser.YamlNode{
Position: parser.FilePosition{Lines: []int{11}},
Value: `Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}`,
},
},
},
},
},
},
},
},
*/
}

alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
Expand Down
9 changes: 8 additions & 1 deletion internal/reporter/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/cloudflare/pint/internal/checks"
"github.com/cloudflare/pint/internal/output"
"github.com/rs/zerolog/log"
)

func NewConsoleReporter(output io.Writer) ConsoleReporter {
Expand Down Expand Up @@ -68,7 +69,13 @@ func (cr ConsoleReporter) Submit(summary Summary) error {
msg = append(msg, output.MakeGray(report.Problem.Text))
}
msg = append(msg, output.MakeMagneta(" (%s)\n", report.Problem.Reporter))
for _, c := range strings.Split(content, "\n")[firstLine-1 : lastLine] {

lines := strings.Split(content, "\n")
if lastLine > len(lines)-1 {
lastLine = len(lines) - 1
log.Warn().Str("path", report.Path).Msgf("Tried to read more lines than present in the source file, this is likely due to '\n' usage in some rules, see https://github.com/cloudflare/pint/issues/20 for details")
}
for _, c := range lines[firstLine-1 : lastLine] {
msg = append(msg, output.MakeWhite("%s\n", c))
}
perFile[report.Path] = append(perFile[report.Path], strings.Join(msg, ""))
Expand Down

0 comments on commit 3cc8a75

Please sign in to comment.