From a7b6b9efe0f463ff23c12260a21d82a9b9f071aa Mon Sep 17 00:00:00 2001 From: dirc Date: Fri, 12 Jun 2026 15:56:28 +0200 Subject: [PATCH 1/3] fix: handling of duplicate and empty tags --- internal/model/check.go | 16 ++++++++++++--- internal/model/check_test.go | 40 +++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/internal/model/check.go b/internal/model/check.go index b842507..3b02d48 100644 --- a/internal/model/check.go +++ b/internal/model/check.go @@ -58,7 +58,7 @@ func NewUptimeCheck(ingressName string, annotations map[string]string) (*UptimeC ID: id, Name: name, URL: url, - Tags: stringToSlice(annotations[AnnotationTags]), + Tags: parseTags(annotations[AnnotationTags]), Interval: interval, RequestHeaders: kvStringToMap(annotations[AnnotationRequestHeaders]), StringContains: annotations[AnnotationStringContains], @@ -99,14 +99,24 @@ func kvStringToMap(s string) map[string]string { return result } -func stringToSlice(s string) []string { +func parseTags(s string) []string { if s == "" { return nil } + + seen := make(map[string]struct{}) var result []string splits := strings.Split(s, ",") for _, part := range splits { - result = append(result, strings.TrimSpace(part)) + value := strings.TrimSpace(part) + if value == "" { + continue + } + if _, ok := seen[value]; ok { + continue + } + seen[value] = struct{}{} + result = append(result, value) } return result } diff --git a/internal/model/check_test.go b/internal/model/check_test.go index 86904b4..621b6f5 100644 --- a/internal/model/check_test.go +++ b/internal/model/check_test.go @@ -1,6 +1,7 @@ package model import ( + "slices" "testing" ) @@ -9,6 +10,7 @@ func TestNewUptimeCheck(t *testing.T) { name string ingressName string annotations map[string]string + wantTags []string wantErr bool }{ { @@ -23,7 +25,8 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: false, + wantTags: []string{"tag1", "tag2", TagManagedBy}, + wantErr: false, }, { name: "Missing ID annotation", @@ -36,7 +39,8 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: true, + wantTags: nil, + wantErr: true, }, { name: "Missing Name annotation", @@ -49,7 +53,8 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: true, + wantTags: nil, + wantErr: true, }, { name: "Missing URL annotation", @@ -62,7 +67,8 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: true, + wantTags: nil, + wantErr: true, }, { name: "Missing tags annotation", @@ -75,7 +81,8 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: false, + wantTags: []string{TagManagedBy}, + wantErr: false, }, { name: "Missing request-headers annotation", @@ -88,15 +95,34 @@ func TestNewUptimeCheck(t *testing.T) { "uptime.pdok.nl/response-check-for-string-contains": "test string", "uptime.pdok.nl/response-check-for-string-not-contains": "", }, - wantErr: false, + wantTags: []string{"tag1", "tag2", TagManagedBy}, + wantErr: false, + }, + { + name: "Duplicate tags", + ingressName: "test-ingress", + annotations: map[string]string{ + "uptime.pdok.nl/id": "1234567890", + "uptime.pdok.nl/name": "Test Check", + "uptime.pdok.nl/url": "https://pdok.example", + "uptime.pdok.nl/tags": "tag1, tag2, tag1, tag3, tag2, , tag3", + }, + wantTags: []string{"tag1", "tag2", "tag3", TagManagedBy}, + wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := NewUptimeCheck(tt.ingressName, tt.annotations) + check, err := NewUptimeCheck(tt.ingressName, tt.annotations) if (err != nil) != tt.wantErr { t.Errorf("NewUptimeCheck() error = %v, wantErr %v", err, tt.wantErr) } + if tt.wantErr || tt.wantTags == nil { + return + } + if !slices.Equal(check.Tags, tt.wantTags) { + t.Errorf("NewUptimeCheck().Tags = %v, want %v", check.Tags, tt.wantTags) + } }) } } From ef7808a3b6f830281cca87660c00d361838f05e7 Mon Sep 17 00:00:00 2001 From: dirc Date: Fri, 12 Jun 2026 15:58:03 +0200 Subject: [PATCH 2/3] fix: correct formatting in error message for response body. Log in string, not in bytes --- internal/service/providers/betterstack/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/service/providers/betterstack/client.go b/internal/service/providers/betterstack/client.go index 62f3c25..2f40ebf 100644 --- a/internal/service/providers/betterstack/client.go +++ b/internal/service/providers/betterstack/client.go @@ -32,7 +32,7 @@ func (h Client) execRequest(req *http.Request, expectedStatus int) (*http.Respon if resp.StatusCode != expectedStatus { defer resp.Body.Close() result, _ := io.ReadAll(resp.Body) - return nil, fmt.Errorf("got status %d, expected %d. Body: %b", resp.StatusCode, expectedStatus, result) + return nil, fmt.Errorf("got status %d, expected %d. Body: %s", resp.StatusCode, expectedStatus, result) } return resp, nil // caller should close resp.Body! } From 2edf1961a6e3eecbbaa43bf71c29e3683dc05bdb Mon Sep 17 00:00:00 2001 From: dirc Date: Fri, 12 Jun 2026 16:17:21 +0200 Subject: [PATCH 3/3] chore: revive lint exclusion to allow "util" as package name --- .golangci.yml | 4 ++++ internal/util/flag.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 5d43f97..e343a77 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -95,6 +95,10 @@ linters: - legacy - std-error-handling rules: + - linters: + - revive + text: "var-naming: avoid meaningless package names" + path: internal/util/ - linters: - bodyclose - dogsled diff --git a/internal/util/flag.go b/internal/util/flag.go index 9eb36fc..1701ea6 100644 --- a/internal/util/flag.go +++ b/internal/util/flag.go @@ -1,4 +1,4 @@ -package util //nolint:revive +package util import ( "strings"