From cb7be28f6831951602ac9ddcb63f4e8e6d4c1b33 Mon Sep 17 00:00:00 2001
From: Abdelrahman Ahmed
Date: Sun, 29 Mar 2026 22:22:33 +0200
Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=94=A7=20Refactor=20to=20follow=20Kub?=
=?UTF-8?q?ernetes=20project=20structure=20and=20logging=20standards?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 🗂️ Restructure to use cmd/, internal/, hack/, third_party/ directories
- 📦 Move main.go to cmd/kwatch/
- 🔖 Rename packages: k8sutil→k8s, alertmanager→alert, pvcmonitor→pvc
- 📝 Use underscores for file/directory names per K8s conventions
- 📚 Migrate from logrus to klog (K8s standard logging)
- 🛠️ Add Makefile with K8s-style targets
- 🐳 Update Dockerfile to build from ./cmd/kwatch
---
.github/workflows/check.yml | 2 +-
.gitignore | 2 +-
Dockerfile | 4 +-
Makefile | 101 ++++++++++++++++++
cmd/kwatch/main.go | 81 ++++++++++++++
go.mod | 3 +-
go.sum | 2 -
.../alert/alert.go | 57 +++++-----
.../alert/alert_test.go | 35 +++---
.../alert}/dingtalk/dingtalk.go | 16 +--
.../alert}/dingtalk/dingtalk_test.go | 4 +-
.../alert}/discord/discord.go | 16 +--
.../alert}/discord/discord_test.go | 4 +-
.../alert}/email/email.go | 26 ++---
.../alert}/email/email_test.go | 4 +-
.../alert}/feishu/feishu.go | 14 +--
.../alert}/feishu/feishu_test.go | 4 +-
.../alert}/googlechat/googlechat.go | 14 +--
.../alert}/googlechat/googlechat_test.go | 4 +-
.../alert}/matrix/matrix.go | 22 ++--
.../alert}/matrix/matrix_test.go | 4 +-
.../alert}/mattermost/mattermost.go | 20 ++--
.../alert}/mattermost/mattermost_test.go | 4 +-
.../alert}/opsgenie/opsgenie.go | 16 +--
.../alert}/opsgenie/opsgenie_test.go | 4 +-
.../alert}/pagerduty/pagerduty.go | 14 +--
.../alert}/pagerduty/pagerduty_test.go | 4 +-
.../alert}/rocketchat/rocketchat.go | 14 +--
.../alert}/rocketchat/rocketchat_test.go | 4 +-
.../alert}/slack/slack.go | 18 ++--
.../alert}/slack/slack_test.go | 4 +-
.../alert}/teams/teams.go | 21 ++--
.../alert}/teams/teams_test.go | 4 +-
.../alert}/telegram/telegram.go | 22 ++--
.../alert}/telegram/telegram_test.go | 4 +-
.../alert}/webhook/webhook.go | 22 ++--
.../alert}/webhook/webhook_test.go | 4 +-
.../alert}/zenduty/zenduty.go | 16 +--
.../alert}/zenduty/zenduty_test.go | 4 +-
{client => internal/client}/client.go | 19 +++-
{client => internal/client}/client_test.go | 2 +-
{config => internal/config}/config.go | 0
{config => internal/config}/config_test.go | 0
.../config/default_config.go | 0
.../config/load_config.go | 16 +--
{constant => internal/constant}/constant.go | 0
.../controller}/controller.go | 14 +--
.../controller}/controller_test.go | 2 +-
{event => internal/event}/event.go | 0
{event => internal/event}/event_test.go | 0
{event => internal/event}/format.go | 2 +-
.../filter/container_killing_filter.go | 0
.../filter/container_logs_filter.go | 12 +--
.../filter/container_name_filter.go | 8 +-
.../filter/container_reasons_filter.go | 14 +--
.../filter/container_restarts_filter.go | 0
.../filter/container_state_filter.go | 0
.../filter/event_filter.go | 0
{filter => internal/filter}/filter.go | 4 +-
{filter => internal/filter}/filter_test.go | 6 +-
.../filter/namespace_filter.go | 14 +--
.../filter/pod_events_filter.go | 0
.../filter/pod_name_filter.go | 8 +-
.../filter/pod_owners_filter.go | 0
.../filter/pod_status_filter.go | 18 ++--
.../handler/execute_containers_filters.go | 28 ++---
.../handler/execute_pod_filters.go | 14 +--
{handler => internal/handler}/handler.go | 12 +--
{handler => internal/handler}/handler_test.go | 42 ++++----
.../handler/process_node.go | 8 +-
.../handler/process_pod.go | 6 +-
{health => internal/health}/health.go | 10 +-
{health => internal/health}/health_test.go | 2 +-
{util => internal/k8s}/http.go | 2 +-
{util => internal/k8s}/util.go | 34 +++---
{util => internal/k8s}/util_test.go | 2 +-
.../pvc/check_usage.go | 10 +-
.../getUsage.go => internal/pvc/get_usage.go | 17 ++-
{pvcmonitor => internal/pvc}/pvc.go | 14 +--
.../pvc/pvc_test.go | 28 ++---
{startup => internal/startup}/startup.go | 22 ++--
{startup => internal/startup}/startup_test.go | 2 +-
{state => internal/state}/retry.go | 4 +-
{state => internal/state}/state.go | 4 +-
{state => internal/state}/state_test.go | 0
.../storage}/memory/memory.go | 2 +-
.../storage}/memory/memory_test.go | 2 +-
{storage => internal/storage}/storage.go | 0
{upgrader => internal/upgrader}/upgrader.go | 26 ++---
.../upgrader}/upgrader_test.go | 42 ++++----
{version => internal/version}/version.go | 0
{version => internal/version}/version_test.go | 0
main.go | 80 --------------
93 files changed, 635 insertions(+), 535 deletions(-)
create mode 100644 Makefile
create mode 100644 cmd/kwatch/main.go
rename alertmanager/alertmanager.go => internal/alert/alert.go (65%)
rename alertmanager/alertmanager_test.go => internal/alert/alert_test.go (77%)
rename {alertmanager => internal/alert}/dingtalk/dingtalk.go (89%)
rename {alertmanager => internal/alert}/dingtalk/dingtalk_test.go (99%)
rename {alertmanager => internal/alert}/discord/discord.go (89%)
rename {alertmanager => internal/alert}/discord/discord_test.go (97%)
rename {alertmanager => internal/alert}/email/email.go (78%)
rename {alertmanager => internal/alert}/email/email_test.go (97%)
rename {alertmanager => internal/alert}/feishu/feishu.go (87%)
rename {alertmanager => internal/alert}/feishu/feishu_test.go (97%)
rename {alertmanager => internal/alert}/googlechat/googlechat.go (84%)
rename {alertmanager => internal/alert}/googlechat/googlechat_test.go (96%)
rename {alertmanager => internal/alert}/matrix/matrix.go (83%)
rename {alertmanager => internal/alert}/matrix/matrix_test.go (97%)
rename {alertmanager => internal/alert}/mattermost/mattermost.go (87%)
rename {alertmanager => internal/alert}/mattermost/mattermost_test.go (96%)
rename {alertmanager => internal/alert}/opsgenie/opsgenie.go (89%)
rename {alertmanager => internal/alert}/opsgenie/opsgenie_test.go (97%)
rename {alertmanager => internal/alert}/pagerduty/pagerduty.go (91%)
rename {alertmanager => internal/alert}/pagerduty/pagerduty_test.go (97%)
rename {alertmanager => internal/alert}/rocketchat/rocketchat.go (85%)
rename {alertmanager => internal/alert}/rocketchat/rocketchat_test.go (96%)
rename {alertmanager => internal/alert}/slack/slack.go (90%)
rename {alertmanager => internal/alert}/slack/slack_test.go (98%)
rename {alertmanager => internal/alert}/teams/teams.go (92%)
rename {alertmanager => internal/alert}/teams/teams_test.go (98%)
rename {alertmanager => internal/alert}/telegram/telegram.go (87%)
rename {alertmanager => internal/alert}/telegram/telegram_test.go (98%)
rename {alertmanager => internal/alert}/webhook/webhook.go (86%)
rename {alertmanager => internal/alert}/webhook/webhook_test.go (97%)
rename {alertmanager => internal/alert}/zenduty/zenduty.go (89%)
rename {alertmanager => internal/alert}/zenduty/zenduty_test.go (97%)
rename {client => internal/client}/client.go (79%)
rename {client => internal/client}/client_test.go (98%)
rename {config => internal/config}/config.go (100%)
rename {config => internal/config}/config_test.go (100%)
rename config/defaultConfig.go => internal/config/default_config.go (100%)
rename config/loadConfig.go => internal/config/load_config.go (83%)
rename {constant => internal/constant}/constant.go (100%)
rename {controller => internal/controller}/controller.go (94%)
rename {controller => internal/controller}/controller_test.go (99%)
rename {event => internal/event}/event.go (100%)
rename {event => internal/event}/event_test.go (100%)
rename {event => internal/event}/format.go (98%)
rename filter/containerKillingFilter.go => internal/filter/container_killing_filter.go (100%)
rename filter/containerLogsFilter.go => internal/filter/container_logs_filter.go (75%)
rename filter/containerNameFilter.go => internal/filter/container_name_filter.go (72%)
rename filter/containerReasonsFilter.go => internal/filter/container_reasons_filter.go (88%)
rename filter/containerRestartsFilter.go => internal/filter/container_restarts_filter.go (100%)
rename filter/containerStateFilter.go => internal/filter/container_state_filter.go (100%)
rename filter/eventFilter.go => internal/filter/event_filter.go (100%)
rename {filter => internal/filter}/filter.go (90%)
rename {filter => internal/filter}/filter_test.go (99%)
rename filter/namespaceFilter.go => internal/filter/namespace_filter.go (66%)
rename filter/podEventsFilter.go => internal/filter/pod_events_filter.go (100%)
rename filter/podNameFilter.go => internal/filter/pod_name_filter.go (66%)
rename filter/podOwnersFilter.go => internal/filter/pod_owners_filter.go (100%)
rename filter/podStatusFilter.go => internal/filter/pod_status_filter.go (85%)
rename handler/executeContainersFilters.go => internal/handler/execute_containers_filters.go (77%)
rename handler/executePodFilters.go => internal/handler/execute_pod_filters.go (69%)
rename {handler => internal/handler}/handler.go (86%)
rename {handler => internal/handler}/handler_test.go (91%)
rename handler/processNode.go => internal/handler/process_node.go (82%)
rename handler/processPod.go => internal/handler/process_pod.go (88%)
rename {health => internal/health}/health.go (85%)
rename {health => internal/health}/health_test.go (98%)
rename {util => internal/k8s}/http.go (96%)
rename {util => internal/k8s}/util.go (90%)
rename {util => internal/k8s}/util_test.go (99%)
rename pvcmonitor/checkUsage.go => internal/pvc/check_usage.go (84%)
rename pvcmonitor/getUsage.go => internal/pvc/get_usage.go (83%)
rename {pvcmonitor => internal/pvc}/pvc.go (75%)
rename pvcmonitor/pvcmonitor_test.go => internal/pvc/pvc_test.go (93%)
rename {startup => internal/startup}/startup.go (71%)
rename {startup => internal/startup}/startup_test.go (99%)
rename {state => internal/state}/retry.go (93%)
rename {state => internal/state}/state.go (97%)
rename {state => internal/state}/state_test.go (100%)
rename {storage => internal/storage}/memory/memory.go (97%)
rename {storage => internal/storage}/memory/memory_test.go (98%)
rename {storage => internal/storage}/storage.go (100%)
rename {upgrader => internal/upgrader}/upgrader.go (79%)
rename {upgrader => internal/upgrader}/upgrader_test.go (88%)
rename {version => internal/version}/version.go (100%)
rename {version => internal/version}/version_test.go (100%)
delete mode 100644 main.go
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index a7896349..1e845bff 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -19,7 +19,7 @@ jobs:
with:
go-version: '1.26'
- name: Build
- run: go build
+ run: go build -o kwatch ./cmd/kwatch
- name: Test
run: go test -race --coverprofile=coverage.txt --covermode=atomic ./...
- name: Upload coverage to Codecov
diff --git a/.gitignore b/.gitignore
index 1648f2e8..9c3c9c19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@
*.dll
*.so
*.dylib
-kwatch
# Test binary, built with `go test -c`
*.test
@@ -16,6 +15,7 @@ coverage.txt
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
+_output/
# Dependency directories (remove the comment below to include it)
# vendor/
diff --git a/Dockerfile b/Dockerfile
index 106fb63f..9ee906e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,8 +12,8 @@ COPY go.mod go.sum /build/
RUN go mod download
COPY . /build/
-RUN sed -i 's/dev/'"${RELEASE_VERSION}"'/g' version/version.go
-RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o kwatch .
+RUN sed -i 's/dev/'"${RELEASE_VERSION}"'/g' internal/version/version.go
+RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o kwatch ./cmd/kwatch
FROM alpine:latest
RUN apk add --update ca-certificates && \
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..542106ff
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,101 @@
+# Makefile for kwatch
+# Following Kubernetes community conventions
+
+.PHONY: build test test-short lint vet clean verify-fmt verify-unit verify-all help
+
+# Binary names
+BINARY_NAME := kwatch
+CMD_DIR := cmd/kwatch
+
+# Go parameters
+GOCMD := go
+GOBUILD := CGO_ENABLED=0 $(GOCMD) build
+GOTEST := $(GOCMD) test
+GOVET := $(GOCMD) vet
+GOFMT := $(GOCMD) fmt
+
+# Build parameters
+VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
+BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
+LDFLAGS := -ldflags "-X github.com/abahmed/kwatch/internal/version.version=$(VERSION) -X github.com/abahmed/kwatch/internal/version.gitCommitID=$(shell git rev-parse --short HEAD 2>/dev/null || echo "none") -X github.com/abahmed/kwatch/internal/version.buildDate=$(BUILD_TIME)"
+
+# Output directory
+OUTPUT_DIR := _output
+
+# Default target
+help:
+ @echo "kwatch Makefile"
+ @echo ""
+ @echo "Usage:"
+ @echo " make build Build the binary"
+ @echo " make test Run all tests"
+ @echo " make test-short Run short tests only"
+ @echo " make vet Run go vet"
+ @echo " make lint Run linting (requires golangci-lint)"
+ @echo " make verify-fmt Verify code formatting"
+ @echo " make verify-unit Run unit tests"
+ @echo " make verify-all Run all verification scripts"
+ @echo " make clean Clean build artifacts"
+ @echo ""
+
+# Build the binary
+build:
+ @echo "Building $(BINARY_NAME)..."
+ @mkdir -p $(OUTPUT_DIR)
+ $(GOBUILD) $(LDFLAGS) -o $(OUTPUT_DIR)/$(BINARY_NAME) ./$(CMD_DIR)
+
+# Run tests
+test:
+ @echo "Running tests..."
+ $(GOTEST) -v ./...
+
+# Run short tests
+test-short:
+ @echo "Running short tests..."
+ $(GOTEST) -short ./...
+
+# Run go vet
+vet:
+ @echo "Running go vet..."
+ $(GOVET) ./...
+
+# Run linting
+lint:
+ @echo "Running golangci-lint..."
+ @which golangci-lint > /dev/null || (echo "golangci-lint not found. Install: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" && exit 1)
+ golangci-lint run ./...
+
+# Verify code formatting
+verify-fmt:
+ @echo "Verifying code formatting..."
+ @diff=$$(gofmt -l .); \
+ if [ -n "$$diff" ]; then \
+ echo "The following files are not formatted correctly:"; \
+ echo "$$diff"; \
+ exit 1; \
+ fi
+ @echo "All files are properly formatted."
+
+# Run unit tests
+verify-unit:
+ @echo "Running unit tests..."
+ $(GOTEST) -short ./...
+
+# Run all verification scripts
+verify-all: verify-fmt vet verify-unit
+
+# Clean build artifacts
+clean:
+ @echo "Cleaning..."
+ @rm -rf $(OUTPUT_DIR)
+ @rm -f coverage.out coverage.txt
+ @echo "Clean complete."
+
+# Docker build
+docker-build:
+ @echo "Building Docker image..."
+ docker build -t kwatch:$(VERSION) .
+
+# Docker build with latest tag
+docker-build-latest:
+ docker build -t kwatch:latest -t kwatch:$(VERSION) .
diff --git a/cmd/kwatch/main.go b/cmd/kwatch/main.go
new file mode 100644
index 00000000..376e33f7
--- /dev/null
+++ b/cmd/kwatch/main.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "os/signal"
+ "syscall"
+
+ "github.com/abahmed/kwatch/internal/client"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/controller"
+ "github.com/abahmed/kwatch/internal/handler"
+ "github.com/abahmed/kwatch/internal/health"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "github.com/abahmed/kwatch/internal/pvc"
+ "github.com/abahmed/kwatch/internal/startup"
+ "github.com/abahmed/kwatch/internal/storage/memory"
+ "github.com/abahmed/kwatch/internal/upgrader"
+ "github.com/abahmed/kwatch/internal/version"
+ "k8s.io/klog/v2"
+)
+
+func main() {
+ cfg, err := config.LoadConfig()
+ if err != nil {
+ klog.ErrorS(err, "failed to load config")
+ os.Exit(1)
+ }
+
+ klog.InfoS(fmt.Sprintf(constant.WelcomeMsg, version.Short()))
+
+ k8sClient := client.Create(&cfg.App)
+
+ sm := startup.NewStartupManager(
+ k8sClient,
+ k8s.GetNamespace(),
+ cfg.Alert,
+ &cfg.App,
+ )
+ sm.HandleStartup(context.Background())
+
+ healthServer := health.NewHealthServer(cfg.HealthCheck)
+ healthServer.Start(context.Background())
+
+ up := upgrader.NewUpgrader(&cfg.Upgrader, sm.GetAlertManager(), sm.GetStateManager())
+ go up.CheckUpdates()
+
+ pvcMonitor := pvc.NewPvcMonitor(k8sClient, &cfg.PvcMonitor, sm.GetAlertManager())
+ go pvcMonitor.Start()
+
+ h := handler.NewHandler(
+ k8sClient,
+ cfg,
+ memory.NewMemory(),
+ sm.GetAlertManager(),
+ )
+
+ ctrl, cleanup := controller.New(k8sClient, cfg, h)
+ defer cleanup()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ go func() {
+ if err := ctrl.Run(ctx, 1); err != nil {
+ klog.ErrorS(err, "controller error")
+ os.Exit(1)
+ }
+ }()
+
+ sigCh := make(chan os.Signal, 1)
+ signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
+ <-sigCh
+
+ klog.InfoS("shutting down gracefully...")
+ cancel()
+ healthServer.Stop(context.Background())
+ os.Exit(0)
+}
diff --git a/go.mod b/go.mod
index 41a2331e..19354d85 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,6 @@ go 1.26.1
require (
github.com/bwmarrin/discordgo v0.29.0
github.com/google/go-github/v41 v41.0.1-0.20211227215900-a899e0fadbec
- github.com/sirupsen/logrus v1.9.4
github.com/slack-go/slack v0.20.0
github.com/stretchr/testify v1.11.1
gopkg.in/mail.v2 v2.3.1
@@ -13,6 +12,7 @@ require (
k8s.io/api v0.35.3
k8s.io/apimachinery v0.35.3
k8s.io/client-go v0.35.3
+ k8s.io/klog/v2 v2.140.0
)
require (
@@ -62,7 +62,6 @@ require (
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
- k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
diff --git a/go.sum b/go.sum
index 4da268ba..721d98ab 100644
--- a/go.sum
+++ b/go.sum
@@ -81,8 +81,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
-github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
-github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
github.com/slack-go/slack v0.20.0 h1:gbDdbee8+Z2o+DWx05Spq3GzbrLLleiRwHUKs+hZLSU=
github.com/slack-go/slack v0.20.0/go.mod h1:K81UmCivcYd/5Jmz8vLBfuyoZ3B4rQC2GHVXHteXiAE=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
diff --git a/alertmanager/alertmanager.go b/internal/alert/alert.go
similarity index 65%
rename from alertmanager/alertmanager.go
rename to internal/alert/alert.go
index eab4e66d..ecce139b 100644
--- a/alertmanager/alertmanager.go
+++ b/internal/alert/alert.go
@@ -1,27 +1,27 @@
-package alertmanager
+package alert
import (
"reflect"
"strings"
- "github.com/abahmed/kwatch/alertmanager/dingtalk"
- "github.com/abahmed/kwatch/alertmanager/discord"
- "github.com/abahmed/kwatch/alertmanager/email"
- "github.com/abahmed/kwatch/alertmanager/feishu"
- "github.com/abahmed/kwatch/alertmanager/googlechat"
- "github.com/abahmed/kwatch/alertmanager/matrix"
- "github.com/abahmed/kwatch/alertmanager/mattermost"
- "github.com/abahmed/kwatch/alertmanager/opsgenie"
- "github.com/abahmed/kwatch/alertmanager/pagerduty"
- "github.com/abahmed/kwatch/alertmanager/rocketchat"
- "github.com/abahmed/kwatch/alertmanager/slack"
- "github.com/abahmed/kwatch/alertmanager/teams"
- "github.com/abahmed/kwatch/alertmanager/telegram"
- "github.com/abahmed/kwatch/alertmanager/webhook"
- "github.com/abahmed/kwatch/alertmanager/zenduty"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/alert/dingtalk"
+ "github.com/abahmed/kwatch/internal/alert/discord"
+ "github.com/abahmed/kwatch/internal/alert/email"
+ "github.com/abahmed/kwatch/internal/alert/feishu"
+ "github.com/abahmed/kwatch/internal/alert/googlechat"
+ "github.com/abahmed/kwatch/internal/alert/matrix"
+ "github.com/abahmed/kwatch/internal/alert/mattermost"
+ "github.com/abahmed/kwatch/internal/alert/opsgenie"
+ "github.com/abahmed/kwatch/internal/alert/pagerduty"
+ "github.com/abahmed/kwatch/internal/alert/rocketchat"
+ "github.com/abahmed/kwatch/internal/alert/slack"
+ "github.com/abahmed/kwatch/internal/alert/teams"
+ "github.com/abahmed/kwatch/internal/alert/telegram"
+ "github.com/abahmed/kwatch/internal/alert/webhook"
+ "github.com/abahmed/kwatch/internal/alert/zenduty"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "k8s.io/klog/v2"
)
type AlertManager struct {
@@ -83,29 +83,26 @@ func (a *AlertManager) Init(
// Notify sends string msg to all providers
func (a *AlertManager) Notify(msg string) {
- logrus.Infof("sending message: %s", msg)
+ klog.InfoS("sending message", "msg", msg)
for _, prv := range a.providers {
if err := prv.SendMessage(msg); err != nil {
- logrus.Errorf(
- "failed to send msg with %s: %s",
- prv.Name(),
- err.Error())
+ klog.ErrorS(err,
+ "failed to send msg",
+ "provider", prv.Name())
}
}
}
// NotifyEvent sends event to all providers
func (a *AlertManager) NotifyEvent(event event.Event) {
- logrus.Infof("sending event: %+v", event)
+ klog.InfoS("sending event", "event", event)
for _, prv := range a.providers {
if err := prv.SendEvent(&event); err != nil {
- logrus.Errorf(
- "failed to send event with %s: %s",
- prv.Name(),
- err.Error(),
- )
+ klog.ErrorS(err,
+ "failed to send event",
+ "provider", prv.Name())
}
}
}
diff --git a/alertmanager/alertmanager_test.go b/internal/alert/alert_test.go
similarity index 77%
rename from alertmanager/alertmanager_test.go
rename to internal/alert/alert_test.go
index eff3168e..60bf556a 100644
--- a/alertmanager/alertmanager_test.go
+++ b/internal/alert/alert_test.go
@@ -1,11 +1,11 @@
-package alertmanager
+package alert
import (
"errors"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
@@ -32,11 +32,12 @@ func (p *fakeProviderWithError) SendEvent(evt *event.Event) error {
func (p *fakeProviderWithError) Name() string {
return "Slack Error"
}
+
func TestAlertManagerNoConfig(t *testing.T) {
assert := assert.New(t)
- alertmanager := AlertManager{}
- alertmanager.Init(nil, nil)
- assert.Len(alertmanager.providers, 0)
+ am := AlertManager{}
+ am.Init(nil, nil)
+ assert.Len(am.providers, 0)
}
func TestGetProviders(t *testing.T) {
@@ -97,31 +98,31 @@ func TestGetProviders(t *testing.T) {
},
}
- alertmanager := AlertManager{}
- alertmanager.Init(alertMap, &config.App{ClusterName: "dev"})
+ am := AlertManager{}
+ am.Init(alertMap, &config.App{ClusterName: "dev"})
assert.Len(
- alertmanager.providers,
+ am.providers,
len(alertMap),
"get providers returned %d expected %d")
}
func TestSendProvidersEvent(t *testing.T) {
- alertmanager := AlertManager{}
- alertmanager.providers = append(
- alertmanager.providers,
+ am := AlertManager{}
+ am.providers = append(
+ am.providers,
&fakeProvider{},
&fakeProviderWithError{},
)
- alertmanager.NotifyEvent(event.Event{})
+ am.NotifyEvent(event.Event{})
}
func TestSendProvidersMsg(t *testing.T) {
- alertmanager := AlertManager{}
- alertmanager.providers = append(
- alertmanager.providers,
+ am := AlertManager{}
+ am.providers = append(
+ am.providers,
&fakeProvider{},
&fakeProviderWithError{},
)
- alertmanager.Notify("hello world!")
+ am.Notify("hello world!")
}
diff --git a/alertmanager/dingtalk/dingtalk.go b/internal/alert/dingtalk/dingtalk.go
similarity index 89%
rename from alertmanager/dingtalk/dingtalk.go
rename to internal/alert/dingtalk/dingtalk.go
index 03d2a1fd..8541731b 100644
--- a/alertmanager/dingtalk/dingtalk.go
+++ b/internal/alert/dingtalk/dingtalk.go
@@ -12,11 +12,11 @@ import (
"net/url"
"time"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
const (
@@ -42,11 +42,11 @@ type DingTalk struct {
func NewDingTalk(config map[string]interface{}, appCfg *config.App) *DingTalk {
accessToken, ok := config["accessToken"].(string)
if !ok || len(accessToken) == 0 {
- logrus.Warnf("initializing dingtalk with empty access token")
+ klog.InfoS("initializing dingtalk with empty access token")
return nil
}
- logrus.Infof("initializing dingtalk with access token: %s", accessToken)
+ klog.InfoS("initializing dingtalk with access token", "accessToken", accessToken)
title, _ := config["title"].(string)
secret, _ := config["secret"].(string)
@@ -133,7 +133,7 @@ func (d *DingTalk) sendAPI(msg string) error {
request.Header.Set("Content-Type", "application/json")
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
response, err := client.Do(request)
if err != nil {
return err
diff --git a/alertmanager/dingtalk/dingtalk_test.go b/internal/alert/dingtalk/dingtalk_test.go
similarity index 99%
rename from alertmanager/dingtalk/dingtalk_test.go
rename to internal/alert/dingtalk/dingtalk_test.go
index 056d8453..9914f9d2 100644
--- a/alertmanager/dingtalk/dingtalk_test.go
+++ b/internal/alert/dingtalk/dingtalk_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/discord/discord.go b/internal/alert/discord/discord.go
similarity index 89%
rename from alertmanager/discord/discord.go
rename to internal/alert/discord/discord.go
index c38740e7..9294c448 100644
--- a/alertmanager/discord/discord.go
+++ b/internal/alert/discord/discord.go
@@ -3,12 +3,12 @@ package discord
import (
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
discordgo "github.com/bwmarrin/discordgo"
- "github.com/sirupsen/logrus"
+ "k8s.io/klog/v2"
)
const (
@@ -34,16 +34,16 @@ type Discord struct {
func NewDiscord(config map[string]interface{}, appCfg *config.App) *Discord {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing discord with empty webhook url")
+ klog.InfoS("initializing discord with empty webhook url")
return nil
}
webhookList := strings.Split(webhook, "/")
if len(webhookList) <= 1 {
- logrus.Warnf("initializing discord with missing id or token")
+ klog.InfoS("initializing discord with missing id or token")
return nil
}
- logrus.Infof("initializing discord with webhook url: %s", webhook)
+ klog.InfoS("initializing discord with webhook url", "webhook", webhook)
webhookToken := webhookList[len(webhookList)-1]
webhookID := webhookList[len(webhookList)-2]
@@ -70,7 +70,7 @@ func (s *Discord) Name() string {
// SendEvent sends event to the provider
func (s *Discord) SendEvent(ev *event.Event) error {
- logrus.Debugf("sending to discord event: %v", ev)
+ klog.V(4).InfoS("sending to discord event", "event", ev)
// initialize fields with basic info
fields := []*discordgo.MessageEmbedField{
diff --git a/alertmanager/discord/discord_test.go b/internal/alert/discord/discord_test.go
similarity index 97%
rename from alertmanager/discord/discord_test.go
rename to internal/alert/discord/discord_test.go
index 344aa69a..d1699c30 100644
--- a/alertmanager/discord/discord_test.go
+++ b/internal/alert/discord/discord_test.go
@@ -4,8 +4,8 @@ import (
"strings"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
discordgo "github.com/bwmarrin/discordgo"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/email/email.go b/internal/alert/email/email.go
similarity index 78%
rename from alertmanager/email/email.go
rename to internal/alert/email/email.go
index aed11ef3..25913854 100644
--- a/alertmanager/email/email.go
+++ b/internal/alert/email/email.go
@@ -6,11 +6,11 @@ import (
"strconv"
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
gomail "gopkg.in/mail.v2"
+ "k8s.io/klog/v2"
)
type Email struct {
@@ -26,41 +26,41 @@ type Email struct {
func NewEmail(config map[string]interface{}, appCfg *config.App) *Email {
from, ok := config["from"].(string)
if !ok || len(from) == 0 {
- logrus.Warnf("initializing email with an empty from")
+ klog.InfoS("initializing email with an empty from")
return nil
}
to, ok := config["to"].(string)
if !ok || len(to) == 0 {
- logrus.Warnf("initializing email with an empty to")
+ klog.InfoS("initializing email with an empty to")
return nil
}
password, ok := config["password"].(string)
if !ok || len(password) == 0 {
- logrus.Warnf("initializing email with an empty password")
+ klog.InfoS("initializing email with an empty password")
return nil
}
host, ok := config["host"].(string)
if !ok || len(host) == 0 {
- logrus.Warnf("initializing email with an empty host")
+ klog.InfoS("initializing email with an empty host")
return nil
}
port, ok := config["port"].(string)
if !ok || len(port) == 0 {
- logrus.Warnf("initializing email with an empty port number")
+ klog.InfoS("initializing email with an empty port number")
return nil
}
portNumber, err := strconv.Atoi(port)
if err != nil {
- logrus.Warnf("initializing email with an invalid port number: %s", err)
+ klog.InfoS("initializing email with an invalid port number", "error", err)
return nil
}
if portNumber > math.MaxUint16 {
- logrus.Warnf("initializing email with an invalid range for port number")
+ klog.InfoS("initializing email with an invalid range for port number")
return nil
}
@@ -105,13 +105,13 @@ func (e *Email) buildMessageSubjectAndBody(
// add events part if it exists
events := strings.TrimSpace(ev.Events)
if len(events) > 0 {
- eventsText = util.JsonEscape(ev.Events)
+ eventsText = k8s.JsonEscape(ev.Events)
}
// add logs part if it exists
logs := strings.TrimSpace(ev.Logs)
if len(logs) > 0 {
- logsText = util.JsonEscape(ev.Logs)
+ logsText = k8s.JsonEscape(ev.Logs)
}
subject := fmt.Sprintf("⛑ Kwatch detected a crash in pod %s ", ev.ContainerName)
diff --git a/alertmanager/email/email_test.go b/internal/alert/email/email_test.go
similarity index 97%
rename from alertmanager/email/email_test.go
rename to internal/alert/email/email_test.go
index 409c9adf..8a0de3ea 100644
--- a/alertmanager/email/email_test.go
+++ b/internal/alert/email/email_test.go
@@ -3,8 +3,8 @@ package email
import (
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
gomail "gopkg.in/mail.v2"
)
diff --git a/alertmanager/feishu/feishu.go b/internal/alert/feishu/feishu.go
similarity index 87%
rename from alertmanager/feishu/feishu.go
rename to internal/alert/feishu/feishu.go
index 97917bc4..e0e3dd85 100644
--- a/alertmanager/feishu/feishu.go
+++ b/internal/alert/feishu/feishu.go
@@ -7,10 +7,10 @@ import (
"io"
"net/http"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type FeiShu struct {
@@ -30,11 +30,11 @@ type feiShuWebhookContent struct {
func NewFeiShu(config map[string]interface{}, appCfg *config.App) *FeiShu {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing Fei Shu with empty webhook url")
+ klog.InfoS("initializing Fei Shu with empty webhook url")
return nil
}
- logrus.Infof("initializing Fei Shu with webhook url: %s", webhook)
+ klog.InfoS("initializing Fei Shu with webhook url", "webhook", webhook)
title, _ := config["title"].(string)
@@ -58,7 +58,7 @@ func (r *FeiShu) SendEvent(e *event.Event) error {
}
func (r *FeiShu) sendByFeiShuApi(reqBody string) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer([]byte(reqBody))
request, err := http.NewRequest(http.MethodPost, r.webhook, buffer)
if err != nil {
diff --git a/alertmanager/feishu/feishu_test.go b/internal/alert/feishu/feishu_test.go
similarity index 97%
rename from alertmanager/feishu/feishu_test.go
rename to internal/alert/feishu/feishu_test.go
index 259a3ece..1a69739f 100644
--- a/alertmanager/feishu/feishu_test.go
+++ b/internal/alert/feishu/feishu_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/googlechat/googlechat.go b/internal/alert/googlechat/googlechat.go
similarity index 84%
rename from alertmanager/googlechat/googlechat.go
rename to internal/alert/googlechat/googlechat.go
index 8680c140..97bed91d 100644
--- a/alertmanager/googlechat/googlechat.go
+++ b/internal/alert/googlechat/googlechat.go
@@ -7,10 +7,10 @@ import (
"io"
"net/http"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type GoogleChat struct {
@@ -29,11 +29,11 @@ type payload struct {
func NewGoogleChat(config map[string]interface{}, appCfg *config.App) *GoogleChat {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing Google Chat with empty webhook url")
+ klog.InfoS("initializing Google Chat with empty webhook url")
return nil
}
- logrus.Infof("initializing Google Chat with webhook url: %s", webhook)
+ klog.InfoS("initializing Google Chat with webhook url", "webhook", webhook)
text, _ := config["text"].(string)
@@ -56,7 +56,7 @@ func (r *GoogleChat) SendEvent(e *event.Event) error {
}
func (r *GoogleChat) sendAPI(reqBody string) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer([]byte(reqBody))
request, err := http.NewRequest(http.MethodPost, r.webhook, buffer)
if err != nil {
diff --git a/alertmanager/googlechat/googlechat_test.go b/internal/alert/googlechat/googlechat_test.go
similarity index 96%
rename from alertmanager/googlechat/googlechat_test.go
rename to internal/alert/googlechat/googlechat_test.go
index 8309e2ab..d0b6dbd2 100644
--- a/alertmanager/googlechat/googlechat_test.go
+++ b/internal/alert/googlechat/googlechat_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/matrix/matrix.go b/internal/alert/matrix/matrix.go
similarity index 83%
rename from alertmanager/matrix/matrix.go
rename to internal/alert/matrix/matrix.go
index e3445cec..db207571 100644
--- a/alertmanager/matrix/matrix.go
+++ b/internal/alert/matrix/matrix.go
@@ -8,10 +8,10 @@ import (
"net/url"
"regexp"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type Matrix struct {
@@ -29,19 +29,19 @@ type Matrix struct {
func NewMatrix(config map[string]interface{}, appCfg *config.App) *Matrix {
homeServer, ok := config["homeServer"].(string)
if !ok || len(homeServer) == 0 {
- logrus.Warnf("initializing slack with empty homeServer")
+ klog.InfoS("initializing matrix with empty homeServer")
return nil
}
accessToken, ok := config["accessToken"].(string)
if !ok || len(accessToken) == 0 {
- logrus.Warnf("initializing slack with empty accessToken")
+ klog.InfoS("initializing matrix with empty accessToken")
return nil
}
internalRoomID, ok := config["internalRoomId"].(string)
if !ok || len(internalRoomID) == 0 {
- logrus.Warnf("initializing slack with empty internalRoomId")
+ klog.InfoS("initializing matrix with empty internalRoomId")
return nil
}
@@ -78,8 +78,8 @@ func (m *Matrix) sendAPI(formattedMsg string) error {
"body": "%s",
"formatted_body": "%s"
}`,
- util.JsonEscape(plainMsg),
- util.JsonEscape(formattedMsg),
+ k8s.JsonEscape(plainMsg),
+ k8s.JsonEscape(formattedMsg),
)
request, err := http.NewRequest(
http.MethodPut,
@@ -88,7 +88,7 @@ func (m *Matrix) sendAPI(formattedMsg string) error {
"?access_token=%s",
m.homeServer,
url.PathEscape(m.internalRoomID),
- util.RandomString(24),
+ k8s.RandomString(24),
url.QueryEscape(m.accessToken),
),
bytes.NewBuffer([]byte(msg)),
@@ -98,7 +98,7 @@ func (m *Matrix) sendAPI(formattedMsg string) error {
}
request.Header.Set("Content-Type", "application/json")
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
response, err := client.Do(request)
if err != nil {
return err
diff --git a/alertmanager/matrix/matrix_test.go b/internal/alert/matrix/matrix_test.go
similarity index 97%
rename from alertmanager/matrix/matrix_test.go
rename to internal/alert/matrix/matrix_test.go
index d3766299..9537a8a5 100644
--- a/alertmanager/matrix/matrix_test.go
+++ b/internal/alert/matrix/matrix_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/mattermost/mattermost.go b/internal/alert/mattermost/mattermost.go
similarity index 87%
rename from alertmanager/mattermost/mattermost.go
rename to internal/alert/mattermost/mattermost.go
index 34887662..34d1c716 100644
--- a/alertmanager/mattermost/mattermost.go
+++ b/internal/alert/mattermost/mattermost.go
@@ -8,11 +8,11 @@ import (
"net/http"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type Mattermost struct {
@@ -45,11 +45,11 @@ type mmPayload struct {
func NewMattermost(config map[string]interface{}, appCfg *config.App) *Mattermost {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing mattermost with empty webhook url")
+ klog.InfoS("initializing mattermost with empty webhook url")
return nil
}
- logrus.Infof("initializing mattermost with webhook url: %s", webhook)
+ klog.InfoS("initializing mattermost with webhook url", "webhook", webhook)
title, _ := config["title"].(string)
text, _ := config["text"].(string)
@@ -69,20 +69,20 @@ func (m *Mattermost) Name() string {
// SendMessage sends text message to the provider
func (m *Mattermost) SendMessage(msg string) error {
- logrus.Debugf("sending to mattermost msg: %s", msg)
+ klog.V(4).InfoS("sending to mattermost msg", "msg", msg)
return m.sendAPI(m.buildMessage(nil, &msg))
}
// SendEvent sends event to the provider
func (m *Mattermost) SendEvent(e *event.Event) error {
- logrus.Debugf("sending to mattermost event: %v", e)
+ klog.V(4).InfoS("sending to mattermost event", "event", e)
return m.sendAPI(m.buildMessage(e, nil))
}
func (m *Mattermost) sendAPI(content []byte) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer(content)
request, err := http.NewRequest(http.MethodPost, m.webhook, buffer)
if err != nil {
diff --git a/alertmanager/mattermost/mattermost_test.go b/internal/alert/mattermost/mattermost_test.go
similarity index 96%
rename from alertmanager/mattermost/mattermost_test.go
rename to internal/alert/mattermost/mattermost_test.go
index 7a6c309d..7ddeebf5 100644
--- a/alertmanager/mattermost/mattermost_test.go
+++ b/internal/alert/mattermost/mattermost_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/opsgenie/opsgenie.go b/internal/alert/opsgenie/opsgenie.go
similarity index 89%
rename from alertmanager/opsgenie/opsgenie.go
rename to internal/alert/opsgenie/opsgenie.go
index db9de5fb..9f14d3b7 100644
--- a/alertmanager/opsgenie/opsgenie.go
+++ b/internal/alert/opsgenie/opsgenie.go
@@ -7,11 +7,11 @@ import (
"io"
"net/http"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
const (
@@ -41,11 +41,11 @@ type ogPayload struct {
func NewOpsgenie(config map[string]interface{}, appCfg *config.App) *Opsgenie {
apiKey, ok := config["apiKey"].(string)
if !ok || len(apiKey) == 0 {
- logrus.Warnf("initializing opsgenie with empty webhook url")
+ klog.InfoS("initializing opsgenie with empty webhook url")
return nil
}
- logrus.Infof("initializing opsgenie with secret apikey")
+ klog.InfoS("initializing opsgenie with secret apikey")
title, _ := config["title"].(string)
text, _ := config["text"].(string)
@@ -76,7 +76,7 @@ func (m *Opsgenie) SendEvent(e *event.Event) error {
// sendAPI sends http request to Opsgenie API
func (m *Opsgenie) sendAPI(content []byte) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer(content)
request, err := http.NewRequest(http.MethodPost, m.url, buffer)
if err != nil {
diff --git a/alertmanager/opsgenie/opsgenie_test.go b/internal/alert/opsgenie/opsgenie_test.go
similarity index 97%
rename from alertmanager/opsgenie/opsgenie_test.go
rename to internal/alert/opsgenie/opsgenie_test.go
index 077ff0cc..09a5e9fc 100644
--- a/alertmanager/opsgenie/opsgenie_test.go
+++ b/internal/alert/opsgenie/opsgenie_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/pagerduty/pagerduty.go b/internal/alert/pagerduty/pagerduty.go
similarity index 91%
rename from alertmanager/pagerduty/pagerduty.go
rename to internal/alert/pagerduty/pagerduty.go
index 072b8f03..0dd6cb6b 100644
--- a/alertmanager/pagerduty/pagerduty.go
+++ b/internal/alert/pagerduty/pagerduty.go
@@ -7,10 +7,10 @@ import (
"net/http"
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
const (
@@ -54,11 +54,11 @@ type Pagerduty struct {
func NewPagerDuty(config map[string]interface{}, appCfg *config.App) *Pagerduty {
integrationKey, ok := config["integrationKey"].(string)
if !ok || len(integrationKey) == 0 {
- logrus.Warnf("initializing pagerduty with an empty integration key")
+ klog.InfoS("initializing pagerduty with an empty integration key")
return nil
}
- logrus.Infof("initializing pagerduty with the provided integration key")
+ klog.InfoS("initializing pagerduty with the provided integration key")
return &Pagerduty{
integrationKey: integrationKey,
@@ -74,7 +74,7 @@ func (s *Pagerduty) Name() string {
// SendEvent sends event to the provider
func (s *Pagerduty) SendEvent(ev *event.Event) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
reqBody, err := s.buildRequestBodyPagerDuty(ev, s.integrationKey)
if err != nil {
diff --git a/alertmanager/pagerduty/pagerduty_test.go b/internal/alert/pagerduty/pagerduty_test.go
similarity index 97%
rename from alertmanager/pagerduty/pagerduty_test.go
rename to internal/alert/pagerduty/pagerduty_test.go
index c302c1ba..32f2e3d0 100644
--- a/alertmanager/pagerduty/pagerduty_test.go
+++ b/internal/alert/pagerduty/pagerduty_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/rocketchat/rocketchat.go b/internal/alert/rocketchat/rocketchat.go
similarity index 85%
rename from alertmanager/rocketchat/rocketchat.go
rename to internal/alert/rocketchat/rocketchat.go
index e055c68d..1f3c179b 100644
--- a/alertmanager/rocketchat/rocketchat.go
+++ b/internal/alert/rocketchat/rocketchat.go
@@ -7,10 +7,10 @@ import (
"io"
"net/http"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type RocketChat struct {
@@ -29,11 +29,11 @@ type rocketChatWebhookPayload struct {
func NewRocketChat(config map[string]interface{}, appCfg *config.App) *RocketChat {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing Rocket Chat with empty webhook url")
+ klog.InfoS("initializing Rocket Chat with empty webhook url")
return nil
}
- logrus.Infof("initializing Rocket Chat with webhook url: %s", webhook)
+ klog.InfoS("initializing Rocket Chat with webhook url", "webhook", webhook)
text, _ := config["text"].(string)
@@ -56,7 +56,7 @@ func (r *RocketChat) SendEvent(e *event.Event) error {
}
func (r *RocketChat) sendByRocketChatApi(reqBody string) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer([]byte(reqBody))
request, err := http.NewRequest(http.MethodPost, r.webhook, buffer)
if err != nil {
diff --git a/alertmanager/rocketchat/rocketchat_test.go b/internal/alert/rocketchat/rocketchat_test.go
similarity index 96%
rename from alertmanager/rocketchat/rocketchat_test.go
rename to internal/alert/rocketchat/rocketchat_test.go
index 689992b9..a1134bfb 100644
--- a/alertmanager/rocketchat/rocketchat_test.go
+++ b/internal/alert/rocketchat/rocketchat_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/slack/slack.go b/internal/alert/slack/slack.go
similarity index 90%
rename from alertmanager/slack/slack.go
rename to internal/alert/slack/slack.go
index 06694706..f917cab6 100644
--- a/alertmanager/slack/slack.go
+++ b/internal/alert/slack/slack.go
@@ -5,12 +5,12 @@ import (
"fmt"
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
- "github.com/sirupsen/logrus"
slackClient "github.com/slack-go/slack"
+ "k8s.io/klog/v2"
)
const (
@@ -42,10 +42,10 @@ func NewSlack(config map[string]interface{}, appCfg *config.App) *Slack {
channel, hasChannel := config["channel"].(string)
if hasToken && len(token) > 0 {
if !hasChannel || len(channel) == 0 {
- logrus.Warnf("initializing slack with token but missing channel")
+ klog.InfoS("initializing slack with token but missing channel")
return nil
}
- logrus.Infof("initializing slack with token and channel: %s", channel)
+ klog.InfoS("initializing slack with token and channel", "channel", channel)
return &Slack{
token: token,
channel: channel,
@@ -59,11 +59,11 @@ func NewSlack(config map[string]interface{}, appCfg *config.App) *Slack {
// webhook mode: requires webhook
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing slack with empty webhook url and no token")
+ klog.InfoS("initializing slack with empty webhook url and no token")
return nil
}
- logrus.Infof("initializing slack with webhook url: %s", webhook)
+ klog.InfoS("initializing slack with webhook url", "webhook", webhook)
return &Slack{
webhook: webhook,
@@ -82,7 +82,7 @@ func (s *Slack) Name() string {
// SendEvent sends event to the provider
func (s *Slack) SendEvent(ev *event.Event) error {
- logrus.Infof("sending to slack event: %v", ev)
+ klog.InfoS("sending to slack event", "event", ev)
// use custom title if it's provided, otherwise use default
title := s.title
diff --git a/alertmanager/slack/slack_test.go b/internal/alert/slack/slack_test.go
similarity index 98%
rename from alertmanager/slack/slack_test.go
rename to internal/alert/slack/slack_test.go
index 929d0d61..106ade47 100644
--- a/alertmanager/slack/slack_test.go
+++ b/internal/alert/slack/slack_test.go
@@ -3,8 +3,8 @@ package slack
import (
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
slackClient "github.com/slack-go/slack"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/teams/teams.go b/internal/alert/teams/teams.go
similarity index 92%
rename from alertmanager/teams/teams.go
rename to internal/alert/teams/teams.go
index d2ea0e8e..28728307 100644
--- a/alertmanager/teams/teams.go
+++ b/internal/alert/teams/teams.go
@@ -9,10 +9,10 @@ import (
"strings"
"time"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
const (
@@ -43,11 +43,11 @@ type teamsFlowPayload struct {
func NewTeams(config map[string]interface{}, appCfg *config.App) *Teams {
webhook, ok := config["webhook"].(string)
if !ok || len(webhook) == 0 {
- logrus.Warnf("initializing Teams with empty flow url")
+ klog.InfoS("initializing Teams with empty flow url")
return nil
}
- logrus.Infof("initializing Teams with flow url: %s", webhook)
+ klog.InfoS("initializing Teams with flow url", "webhook", webhook)
title, _ := config["title"].(string)
text, _ := config["text"].(string)
@@ -104,7 +104,7 @@ func (t *Teams) sendAPI(payload []byte) error {
request.Header.Set("Content-Type", "application/json")
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
resp, err := client.Do(request)
if err != nil {
return fmt.Errorf("failed to create HTTP response: %w", err)
@@ -132,10 +132,9 @@ func (t *Teams) sendAPI(payload []byte) error {
}
if resp.StatusCode == http.StatusAccepted {
- logrus.Warnf("Request accepted by Power Automate flow, "+
- "but not processed immediately. Attempt %d of %d.",
- attempts+1,
- t.maxRetries)
+ klog.InfoS("Request accepted by Power Automate flow, but not processed immediately",
+ "attempt", attempts+1,
+ "maxRetries", t.maxRetries)
} else {
body, err := io.ReadAll(resp.Body)
if err != nil {
diff --git a/alertmanager/teams/teams_test.go b/internal/alert/teams/teams_test.go
similarity index 98%
rename from alertmanager/teams/teams_test.go
rename to internal/alert/teams/teams_test.go
index 0a552de6..3f36a27a 100644
--- a/alertmanager/teams/teams_test.go
+++ b/internal/alert/teams/teams_test.go
@@ -6,8 +6,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/telegram/telegram.go b/internal/alert/telegram/telegram.go
similarity index 87%
rename from alertmanager/telegram/telegram.go
rename to internal/alert/telegram/telegram.go
index 59d6fbb7..11d40a9c 100644
--- a/alertmanager/telegram/telegram.go
+++ b/internal/alert/telegram/telegram.go
@@ -7,9 +7,9 @@ import (
"net/http"
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "k8s.io/klog/v2"
)
const (
@@ -42,20 +42,20 @@ type Telegram struct {
func NewTelegram(config map[string]interface{}, appCfg *config.App) *Telegram {
token, ok := config["token"].(string)
if !ok || len(token) == 0 {
- logrus.Warnf("initializing telegram with empty token")
+ klog.InfoS("initializing telegram with empty token")
return nil
}
chatId, ok := config["chatId"].(string)
if !ok || len(chatId) == 0 {
- logrus.Warnf("initializing telegram with empty chat_id")
+ klog.InfoS("initializing telegram with empty chat_id")
return nil
}
- logrus.Infof(
- "initializing telegram with token %s and chat_id %s",
- maskString(token),
- maskString(chatId))
+ klog.InfoS(
+ "initializing telegram",
+ "token", maskString(token),
+ "chatId", maskString(chatId))
// returns a new telegram object
return &Telegram{
@@ -73,7 +73,7 @@ func (t *Telegram) Name() string {
// SendEvent sends event to the provider
func (t *Telegram) SendEvent(e *event.Event) error {
- logrus.Debugf("sending to telegram event: %v", e)
+ klog.V(4).InfoS("sending to telegram event", "event", e)
reqBody := t.buildRequestBodyTelegram(e, t.chatId, "")
return t.sendByTelegramApi(reqBody)
@@ -81,7 +81,7 @@ func (t *Telegram) SendEvent(e *event.Event) error {
// SendMessage sends text message to the provider
func (t *Telegram) SendMessage(msg string) error {
- logrus.Debugf("sending to telegram msg: %s", msg)
+ klog.V(4).InfoS("sending to telegram msg", "msg", msg)
reqBody := t.buildRequestBodyTelegram(new(event.Event), t.chatId, msg)
return t.sendByTelegramApi(reqBody)
diff --git a/alertmanager/telegram/telegram_test.go b/internal/alert/telegram/telegram_test.go
similarity index 98%
rename from alertmanager/telegram/telegram_test.go
rename to internal/alert/telegram/telegram_test.go
index cfb8a0b5..7682682e 100644
--- a/alertmanager/telegram/telegram_test.go
+++ b/internal/alert/telegram/telegram_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/webhook/webhook.go b/internal/alert/webhook/webhook.go
similarity index 86%
rename from alertmanager/webhook/webhook.go
rename to internal/alert/webhook/webhook.go
index acf44df5..4abfba0f 100644
--- a/alertmanager/webhook/webhook.go
+++ b/internal/alert/webhook/webhook.go
@@ -7,11 +7,11 @@ import (
"net/http"
"strings"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
- "github.com/sirupsen/logrus"
+ "k8s.io/klog/v2"
)
type KeyValue struct {
@@ -40,7 +40,7 @@ func (w *Webhook) SendMessage(msg string) error {
func NewWebhook(config map[string]interface{}, appCfg *config.App) *Webhook {
url, ok := config["url"].(string)
if !ok || len(url) == 0 {
- logrus.Warnf("initializing webhook with empty url")
+ klog.InfoS("initializing webhook with empty url")
return nil
}
rawHeaders, ok := config["headers"]
@@ -63,8 +63,10 @@ func NewWebhook(config map[string]interface{}, appCfg *config.App) *Webhook {
var a Authentication
json.Unmarshal(basicAuthJson, &a)
- logrus.Infof("initializing webhook with url: %s "+
- "with headers: %s and username: %s", url, headers, a.UserName)
+ klog.InfoS("initializing webhook",
+ "url", url,
+ "headers", headers,
+ "username", a.UserName)
return &Webhook{
webhook: url,
@@ -82,7 +84,7 @@ func (w *Webhook) Name() string {
// SendEvent sends event to the provider
func (w *Webhook) SendEvent(ev *event.Event) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
reqBody := w.buildRequestBody(ev)
buffer := bytes.NewBuffer(reqBody)
@@ -123,13 +125,13 @@ func (w *Webhook) buildRequestBody(
// add events part if it exists
events := strings.TrimSpace(ev.Events)
if len(events) > 0 {
- eventsText = util.JsonEscape(ev.Events)
+ eventsText = k8s.JsonEscape(ev.Events)
}
// add logs part if it exists
logs := strings.TrimSpace(ev.Logs)
if len(logs) > 0 {
- logsText = util.JsonEscape(ev.Logs)
+ logsText = k8s.JsonEscape(ev.Logs)
}
postBody, _ := json.Marshal(map[string]interface{}{
diff --git a/alertmanager/webhook/webhook_test.go b/internal/alert/webhook/webhook_test.go
similarity index 97%
rename from alertmanager/webhook/webhook_test.go
rename to internal/alert/webhook/webhook_test.go
index c3900272..0a008f19 100644
--- a/alertmanager/webhook/webhook_test.go
+++ b/internal/alert/webhook/webhook_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/alertmanager/zenduty/zenduty.go b/internal/alert/zenduty/zenduty.go
similarity index 89%
rename from alertmanager/zenduty/zenduty.go
rename to internal/alert/zenduty/zenduty.go
index 889fde67..783f6e8f 100644
--- a/alertmanager/zenduty/zenduty.go
+++ b/internal/alert/zenduty/zenduty.go
@@ -8,11 +8,11 @@ import (
"net/http"
"slices"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
const (
@@ -49,11 +49,11 @@ type zendutyPayload struct {
func NewZenduty(config map[string]interface{}, appCfg *config.App) *Zenduty {
integrationKey, ok := config["integrationKey"].(string)
if !ok || len(integrationKey) == 0 {
- logrus.Warnf("initializing zenduty with empty webhook url")
+ klog.InfoS("initializing zenduty with empty webhook url")
return nil
}
- logrus.Infof("initializing zenduty with secret apikey")
+ klog.InfoS("initializing zenduty with secret apikey")
// If alert type is not provided, or provided with invalid value
// it will fallback to critical type
@@ -87,7 +87,7 @@ func (m *Zenduty) SendEvent(e *event.Event) error {
// sendAPI sends http request to Zenduty API
func (m *Zenduty) sendAPI(content []byte) error {
- client := util.GetDefaultClient()
+ client := k8s.GetDefaultClient()
buffer := bytes.NewBuffer(content)
url := m.url + "/" + m.integrationkey + "/"
request, err := http.NewRequest(http.MethodPost, url, buffer)
diff --git a/alertmanager/zenduty/zenduty_test.go b/internal/alert/zenduty/zenduty_test.go
similarity index 97%
rename from alertmanager/zenduty/zenduty_test.go
rename to internal/alert/zenduty/zenduty_test.go
index b28d1da6..7195a493 100644
--- a/alertmanager/zenduty/zenduty_test.go
+++ b/internal/alert/zenduty/zenduty_test.go
@@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/event"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/event"
"github.com/stretchr/testify/assert"
)
diff --git a/client/client.go b/internal/client/client.go
similarity index 79%
rename from client/client.go
rename to internal/client/client.go
index 001f0003..f27f8d41 100644
--- a/client/client.go
+++ b/internal/client/client.go
@@ -6,12 +6,12 @@ import (
"os"
"path/filepath"
- "github.com/abahmed/kwatch/config"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
+ "k8s.io/klog/v2"
)
// Create returns kubernetes client after initializing it with in-cluster, or
@@ -19,7 +19,8 @@ import (
func Create(appConfig *config.App) kubernetes.Interface {
client, err := CreateClient(appConfig)
if err != nil {
- logrus.Fatalf("failed to create kubernetes client: %v", err)
+ klog.ErrorS(err, "failed to create kubernetes client")
+ os.Exit(1)
}
return client
}
@@ -29,7 +30,7 @@ func CreateClient(appConfig *config.App) (kubernetes.Interface, error) {
// try to use in cluster config
clientConfig, err := rest.InClusterConfig()
if err != nil {
- logrus.Warnf("cannot get kubernetes in cluster config: %v", err)
+ klog.InfoS("cannot get kubernetes in cluster config", "error", err)
// try to use out of cluster config
kubeconfigPath := getKubeconfigPath()
@@ -51,7 +52,7 @@ func CreateClient(appConfig *config.App) (kubernetes.Interface, error) {
return nil, fmt.Errorf("cannot create kubernetes client: %w", err)
}
- logrus.Debugf("created kubernetes client successfully")
+ klog.V(4).InfoS("created kubernetes client successfully")
return clientset, nil
}
@@ -64,3 +65,11 @@ func getKubeconfigPath() string {
}
return kubeconfigPath
}
+
+func GetNamespace() string {
+ namespace := os.Getenv("POD_NAMESPACE")
+ if namespace == "" {
+ return "kwatch"
+ }
+ return namespace
+}
diff --git a/client/client_test.go b/internal/client/client_test.go
similarity index 98%
rename from client/client_test.go
rename to internal/client/client_test.go
index 5154ebcb..288a0232 100644
--- a/client/client_test.go
+++ b/internal/client/client_test.go
@@ -5,7 +5,7 @@ import (
"path/filepath"
"testing"
- "github.com/abahmed/kwatch/config"
+ "github.com/abahmed/kwatch/internal/config"
"github.com/stretchr/testify/assert"
)
diff --git a/config/config.go b/internal/config/config.go
similarity index 100%
rename from config/config.go
rename to internal/config/config.go
diff --git a/config/config_test.go b/internal/config/config_test.go
similarity index 100%
rename from config/config_test.go
rename to internal/config/config_test.go
diff --git a/config/defaultConfig.go b/internal/config/default_config.go
similarity index 100%
rename from config/defaultConfig.go
rename to internal/config/default_config.go
diff --git a/config/loadConfig.go b/internal/config/load_config.go
similarity index 83%
rename from config/loadConfig.go
rename to internal/config/load_config.go
index 053fc8de..686e4c53 100644
--- a/config/loadConfig.go
+++ b/internal/config/load_config.go
@@ -6,8 +6,8 @@ import (
"regexp"
"strings"
- "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
+ "k8s.io/klog/v2"
)
// LoadConfig loads yaml configuration from file if provided, otherwise
@@ -19,13 +19,13 @@ func LoadConfig() (*Config, error) {
config := DefaultConfig()
yamlFile, err := os.ReadFile(configFile)
if err != nil {
- logrus.Warnf("unable to load config file: %s", err.Error())
+ klog.InfoS("unable to load config file", "error", err.Error())
return nil, err
}
err = yaml.Unmarshal(yamlFile, config)
if err != nil {
- logrus.Warnf("unable to parse config file: %s", err.Error())
+ klog.InfoS("unable to parse config file", "error", err.Error())
return nil, err
}
@@ -34,8 +34,8 @@ func LoadConfig() (*Config, error) {
getAllowForbidSlices(config.Namespaces)
if len(config.AllowedNamespaces) > 0 &&
len(config.ForbiddenNamespaces) > 0 {
- logrus.Error(
- "Either allowed or forbidden namespaces must be set. " +
+ klog.ErrorS(nil,
+ "Either allowed or forbidden namespaces must be set. "+
"Can't set both")
}
@@ -44,7 +44,7 @@ func LoadConfig() (*Config, error) {
getAllowForbidSlices(config.Reasons)
if len(config.AllowedReasons) > 0 &&
len(config.ForbiddenReasons) > 0 {
- logrus.Error("Either allowed or forbidden reasons must be set. " +
+ klog.ErrorS(nil, "Either allowed or forbidden reasons must be set. "+
"Can't set both")
}
@@ -52,14 +52,14 @@ func LoadConfig() (*Config, error) {
config.IgnorePodNamePatterns, err =
getCompiledIgnorePatterns(config.IgnorePodNames)
if err != nil {
- logrus.Errorf("Failed to compile pod name pattern: %s", err.Error())
+ klog.ErrorS(err, "Failed to compile pod name pattern")
}
// Prepare ignored log patterns
config.IgnoreLogPatternsCompiled, err =
getCompiledIgnorePatterns(config.IgnoreLogPatterns)
if err != nil {
- logrus.Errorf("Failed to compile log pattern: %s", err.Error())
+ klog.ErrorS(err, "Failed to compile log pattern")
}
// Parse proxy config
diff --git a/constant/constant.go b/internal/constant/constant.go
similarity index 100%
rename from constant/constant.go
rename to internal/constant/constant.go
diff --git a/controller/controller.go b/internal/controller/controller.go
similarity index 94%
rename from controller/controller.go
rename to internal/controller/controller.go
index 3ec3f890..2133417e 100644
--- a/controller/controller.go
+++ b/internal/controller/controller.go
@@ -5,9 +5,8 @@ import (
"fmt"
"time"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/handler"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/handler"
"k8s.io/apimachinery/pkg/api/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
@@ -16,6 +15,7 @@ import (
corev1lister "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
+ "k8s.io/klog/v2"
)
type Controller struct {
@@ -121,9 +121,9 @@ func (c *Controller) Run(ctx context.Context, workers int) error {
defer c.podQueue.ShutDown()
defer c.nodeQueue.ShutDown()
- logrus.Info("starting controller")
+ klog.InfoS("starting controller")
- logrus.Info("waiting for informer caches to sync")
+ klog.InfoS("waiting for informer caches to sync")
syncFns := []cache.InformerSynced{c.podsSynced}
if c.nodesSynced != nil {
syncFns = append(syncFns, c.nodesSynced)
@@ -132,7 +132,7 @@ func (c *Controller) Run(ctx context.Context, workers int) error {
return fmt.Errorf("failed to wait for caches to sync")
}
- logrus.Info("starting workers")
+ klog.InfoS("starting workers")
for i := 0; i < workers; i++ {
go wait.UntilWithContext(ctx, c.runPodWorker, time.Second)
if c.nodesSynced != nil {
@@ -141,7 +141,7 @@ func (c *Controller) Run(ctx context.Context, workers int) error {
}
<-ctx.Done()
- logrus.Info("shutting down workers")
+ klog.InfoS("shutting down workers")
return nil
}
diff --git a/controller/controller_test.go b/internal/controller/controller_test.go
similarity index 99%
rename from controller/controller_test.go
rename to internal/controller/controller_test.go
index c0e55229..2dc8e63c 100644
--- a/controller/controller_test.go
+++ b/internal/controller/controller_test.go
@@ -8,7 +8,7 @@ import (
"testing"
"time"
- "github.com/abahmed/kwatch/config"
+ "github.com/abahmed/kwatch/internal/config"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/event/event.go b/internal/event/event.go
similarity index 100%
rename from event/event.go
rename to internal/event/event.go
diff --git a/event/event_test.go b/internal/event/event_test.go
similarity index 100%
rename from event/event_test.go
rename to internal/event/event_test.go
diff --git a/event/format.go b/internal/event/format.go
similarity index 98%
rename from event/format.go
rename to internal/event/format.go
index bfd46cf3..0965b996 100644
--- a/event/format.go
+++ b/internal/event/format.go
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
- "github.com/abahmed/kwatch/constant"
+ "github.com/abahmed/kwatch/internal/constant"
)
func (e *Event) FormatMarkdown(clusterName, text, delimiter string) string {
diff --git a/filter/containerKillingFilter.go b/internal/filter/container_killing_filter.go
similarity index 100%
rename from filter/containerKillingFilter.go
rename to internal/filter/container_killing_filter.go
diff --git a/filter/containerLogsFilter.go b/internal/filter/container_logs_filter.go
similarity index 75%
rename from filter/containerLogsFilter.go
rename to internal/filter/container_logs_filter.go
index e6e74a6d..663edcb1 100644
--- a/filter/containerLogsFilter.go
+++ b/internal/filter/container_logs_filter.go
@@ -1,8 +1,8 @@
package filter
import (
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type ContainerLogsFilter struct{}
@@ -19,7 +19,7 @@ func (f ContainerLogsFilter) Execute(ctx *Context) bool {
previousLogs = true
}
- logs := util.GetPodContainerLogs(
+ logs := k8s.GetPodContainerLogs(
ctx.Client,
ctx.Pod.Name,
container.Name,
@@ -29,9 +29,9 @@ func (f ContainerLogsFilter) Execute(ctx *Context) bool {
for _, pattern := range ctx.Config.IgnoreLogPatternsCompiled {
if pattern.MatchString(logs) {
- logrus.Infof(
- "skipping container %s logs as it matches the ignore log pattern",
- container.Name)
+ klog.InfoS(
+ "skipping container logs as it matches the ignore log pattern",
+ "container", container.Name)
return true
}
}
diff --git a/filter/containerNameFilter.go b/internal/filter/container_name_filter.go
similarity index 72%
rename from filter/containerNameFilter.go
rename to internal/filter/container_name_filter.go
index 0e4511d1..230b8e09 100644
--- a/filter/containerNameFilter.go
+++ b/internal/filter/container_name_filter.go
@@ -1,8 +1,8 @@
package filter
import (
- "github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
+ "k8s.io/klog/v2"
)
type ContainerNameFilter struct{}
@@ -11,9 +11,9 @@ func (f ContainerNameFilter) Execute(ctx *Context) bool {
container := ctx.Container.Container
if len(ctx.Config.IgnoreContainerNames) > 0 &&
slices.Contains(ctx.Config.IgnoreContainerNames, container.Name) {
- logrus.Infof(
- "skipping container %s as it is in the container ignore list",
- container.Name)
+ klog.InfoS(
+ "skipping container as it is in the container ignore list",
+ "container", container.Name)
return true
}
diff --git a/filter/containerReasonsFilter.go b/internal/filter/container_reasons_filter.go
similarity index 88%
rename from filter/containerReasonsFilter.go
rename to internal/filter/container_reasons_filter.go
index 08ed81e6..0e5a095a 100644
--- a/filter/containerReasonsFilter.go
+++ b/internal/filter/container_reasons_filter.go
@@ -1,8 +1,8 @@
package filter
import (
- "github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
+ "k8s.io/klog/v2"
)
type ContainerReasonsFilter struct{}
@@ -35,17 +35,17 @@ func (f ContainerReasonsFilter) Execute(ctx *Context) bool {
if len(ctx.Config.AllowedReasons) > 0 &&
!slices.Contains(ctx.Config.AllowedReasons, ctx.Container.Reason) {
- logrus.Infof(
- "skipping reason %s as it is not in the reason allow list",
- ctx.Container.Reason)
+ klog.InfoS(
+ "skipping reason as it is not in the reason allow list",
+ "reason", ctx.Container.Reason)
return true
}
if len(ctx.Config.ForbiddenReasons) > 0 &&
slices.Contains(ctx.Config.ForbiddenReasons, ctx.Container.Reason) {
- logrus.Infof(
- "skipping reason %s as it is in the reason forbid list",
- ctx.Container.Reason)
+ klog.InfoS(
+ "skipping reason as it is in the reason forbid list",
+ "reason", ctx.Container.Reason)
return true
}
diff --git a/filter/containerRestartsFilter.go b/internal/filter/container_restarts_filter.go
similarity index 100%
rename from filter/containerRestartsFilter.go
rename to internal/filter/container_restarts_filter.go
diff --git a/filter/containerStateFilter.go b/internal/filter/container_state_filter.go
similarity index 100%
rename from filter/containerStateFilter.go
rename to internal/filter/container_state_filter.go
diff --git a/filter/eventFilter.go b/internal/filter/event_filter.go
similarity index 100%
rename from filter/eventFilter.go
rename to internal/filter/event_filter.go
diff --git a/filter/filter.go b/internal/filter/filter.go
similarity index 90%
rename from filter/filter.go
rename to internal/filter/filter.go
index 3c93d138..96fece23 100644
--- a/filter/filter.go
+++ b/internal/filter/filter.go
@@ -3,8 +3,8 @@ package filter
import (
"time"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/storage"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/storage"
corev1 "k8s.io/api/core/v1"
apiv1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
diff --git a/filter/filter_test.go b/internal/filter/filter_test.go
similarity index 99%
rename from filter/filter_test.go
rename to internal/filter/filter_test.go
index 07eabe57..89199dee 100644
--- a/filter/filter_test.go
+++ b/internal/filter/filter_test.go
@@ -4,9 +4,9 @@ import (
"regexp"
"testing"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/storage"
- "github.com/abahmed/kwatch/storage/memory"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/storage"
+ "github.com/abahmed/kwatch/internal/storage/memory"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/filter/namespaceFilter.go b/internal/filter/namespace_filter.go
similarity index 66%
rename from filter/namespaceFilter.go
rename to internal/filter/namespace_filter.go
index a64098a0..370d8917 100644
--- a/filter/namespaceFilter.go
+++ b/internal/filter/namespace_filter.go
@@ -1,8 +1,8 @@
package filter
import (
- "github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
+ "k8s.io/klog/v2"
)
type NamespaceFilter struct{}
@@ -11,17 +11,17 @@ func (f NamespaceFilter) Execute(ctx *Context) bool {
// filter by namespaces in config if specified
if len(ctx.Config.AllowedNamespaces) > 0 &&
!slices.Contains(ctx.Config.AllowedNamespaces, ctx.Pod.Namespace) {
- logrus.Infof(
- "skipping namespace %s as it is not in the namespace allow list",
- ctx.Pod.Namespace)
+ klog.InfoS(
+ "skipping namespace as it is not in the namespace allow list",
+ "namespace", ctx.Pod.Namespace)
return true
}
if len(ctx.Config.ForbiddenNamespaces) > 0 &&
slices.Contains(ctx.Config.ForbiddenNamespaces, ctx.Pod.Namespace) {
- logrus.Infof(
- "skipping namespace %s as it is in the namespace forbid list",
- ctx.Pod.Namespace)
+ klog.InfoS(
+ "skipping namespace as it is in the namespace forbid list",
+ "namespace", ctx.Pod.Namespace)
return true
}
diff --git a/filter/podEventsFilter.go b/internal/filter/pod_events_filter.go
similarity index 100%
rename from filter/podEventsFilter.go
rename to internal/filter/pod_events_filter.go
diff --git a/filter/podNameFilter.go b/internal/filter/pod_name_filter.go
similarity index 66%
rename from filter/podNameFilter.go
rename to internal/filter/pod_name_filter.go
index c8903b38..cc6272ae 100644
--- a/filter/podNameFilter.go
+++ b/internal/filter/pod_name_filter.go
@@ -1,7 +1,7 @@
package filter
import (
- "github.com/sirupsen/logrus"
+ "k8s.io/klog/v2"
)
type PodNameFilter struct{}
@@ -9,9 +9,9 @@ type PodNameFilter struct{}
func (f PodNameFilter) Execute(ctx *Context) bool {
for _, pattern := range ctx.Config.IgnorePodNamePatterns {
if pattern.MatchString(ctx.Pod.Name) {
- logrus.Infof(
- "skipping pod %s as it is in the ignore pod name list",
- ctx.Pod.Name)
+ klog.InfoS(
+ "skipping pod as it is in the ignore pod name list",
+ "pod", ctx.Pod.Name)
return true
}
}
diff --git a/filter/podOwnersFilter.go b/internal/filter/pod_owners_filter.go
similarity index 100%
rename from filter/podOwnersFilter.go
rename to internal/filter/pod_owners_filter.go
diff --git a/filter/podStatusFilter.go b/internal/filter/pod_status_filter.go
similarity index 85%
rename from filter/podStatusFilter.go
rename to internal/filter/pod_status_filter.go
index 10d782c8..269d56fb 100644
--- a/filter/podStatusFilter.go
+++ b/internal/filter/pod_status_filter.go
@@ -1,9 +1,9 @@
package filter
import (
- "github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/klog/v2"
)
type PodStatusFilter struct{}
@@ -53,20 +53,20 @@ func (f PodStatusFilter) Execute(ctx *Context) bool {
if len(ctx.PodReason) > 0 &&
len(ctx.Config.AllowedReasons) > 0 &&
!slices.Contains(ctx.Config.AllowedReasons, ctx.PodReason) {
- logrus.Infof(
- "skipping reason %s for pod %s as it is not in the reason allow list",
- ctx.PodReason,
- ctx.Pod.Name)
+ klog.InfoS(
+ "skipping reason for pod as it is not in the reason allow list",
+ "reason", ctx.PodReason,
+ "pod", ctx.Pod.Name)
return true
}
if len(ctx.PodReason) > 0 &&
len(ctx.Config.ForbiddenReasons) > 0 &&
slices.Contains(ctx.Config.ForbiddenReasons, ctx.PodReason) {
- logrus.Infof(
- "skipping reason %s for pod %s as it is in the reason forbid list",
- ctx.PodReason,
- ctx.Pod.Name)
+ klog.InfoS(
+ "skipping reason for pod as it is in the reason forbid list",
+ "reason", ctx.PodReason,
+ "pod", ctx.Pod.Name)
return true
}
diff --git a/handler/executeContainersFilters.go b/internal/handler/execute_containers_filters.go
similarity index 77%
rename from handler/executeContainersFilters.go
rename to internal/handler/execute_containers_filters.go
index c807a4c6..1a134ddf 100644
--- a/handler/executeContainersFilters.go
+++ b/internal/handler/execute_containers_filters.go
@@ -3,12 +3,12 @@ package handler
import (
"time"
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/filter"
- "github.com/abahmed/kwatch/storage"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/filter"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "github.com/abahmed/kwatch/internal/storage"
corev1 "k8s.io/api/core/v1"
+ "k8s.io/klog/v2"
)
func (h *handler) executeContainersFilters(ctx *filter.Context) {
@@ -54,14 +54,14 @@ func (h *handler) executeContainersFilters(ctx *filter.Context) {
ownerName = ctx.Owner.Name
}
- logrus.Printf(
- "container only issue %s %s %s %s %s %d",
- ctx.Container.Container.Name,
- ctx.Pod.Name,
- ownerName,
- ctx.Container.Reason,
- ctx.Container.Msg,
- ctx.Container.ExitCode)
+ klog.InfoS(
+ "container only issue",
+ "container", ctx.Container.Container.Name,
+ "pod", ctx.Pod.Name,
+ "owner", ownerName,
+ "reason", ctx.Container.Reason,
+ "message", ctx.Container.Msg,
+ "exitCode", ctx.Container.ExitCode)
h.alertManager.NotifyEvent(event.Event{
PodName: ctx.Pod.Name,
@@ -69,7 +69,7 @@ func (h *handler) executeContainersFilters(ctx *filter.Context) {
Namespace: ctx.Pod.Namespace,
NodeName: ctx.Pod.Spec.NodeName,
Reason: ctx.Container.Reason,
- Events: util.GetPodEventsStr(ctx.Events),
+ Events: k8s.GetPodEventsStr(ctx.Events),
Logs: ctx.Container.Logs,
Labels: ctx.Pod.Labels,
})
diff --git a/handler/executePodFilters.go b/internal/handler/execute_pod_filters.go
similarity index 69%
rename from handler/executePodFilters.go
rename to internal/handler/execute_pod_filters.go
index 1d85194a..1d1cfdb9 100644
--- a/handler/executePodFilters.go
+++ b/internal/handler/execute_pod_filters.go
@@ -1,11 +1,11 @@
package handler
import (
- "github.com/abahmed/kwatch/event"
- "github.com/abahmed/kwatch/filter"
- "github.com/abahmed/kwatch/storage"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/event"
+ "github.com/abahmed/kwatch/internal/filter"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "github.com/abahmed/kwatch/internal/storage"
+ "k8s.io/klog/v2"
)
func (h *handler) executePodFilters(ctx *filter.Context) {
@@ -39,7 +39,7 @@ func (h *handler) executePodFilters(ctx *filter.Context) {
},
)
- logrus.Printf("pod only issue %s %s %s %s", ctx.Pod.Name, ownerName, ctx.PodReason, ctx.PodMsg)
+ klog.InfoS("pod only issue", "pod", ctx.Pod.Name, "owner", ownerName, "reason", ctx.PodReason, "message", ctx.PodMsg)
h.alertManager.NotifyEvent(event.Event{
PodName: ctx.Pod.Name,
@@ -47,7 +47,7 @@ func (h *handler) executePodFilters(ctx *filter.Context) {
Namespace: ctx.Pod.Namespace,
NodeName: ctx.Pod.Spec.NodeName,
Reason: ctx.PodReason,
- Events: util.GetPodEventsStr(ctx.Events),
+ Events: k8s.GetPodEventsStr(ctx.Events),
Logs: "",
Labels: ctx.Pod.Labels,
})
diff --git a/handler/handler.go b/internal/handler/handler.go
similarity index 86%
rename from handler/handler.go
rename to internal/handler/handler.go
index a486ebca..c467ed77 100644
--- a/handler/handler.go
+++ b/internal/handler/handler.go
@@ -1,10 +1,10 @@
package handler
import (
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/filter"
- "github.com/abahmed/kwatch/storage"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/filter"
+ "github.com/abahmed/kwatch/internal/storage"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
corev1lister "k8s.io/client-go/listers/core/v1"
@@ -25,7 +25,7 @@ type handler struct {
memory storage.Storage
podFilters []filter.Filter
containerFilters []filter.Filter
- alertManager *alertmanager.AlertManager
+ alertManager *alert.AlertManager
podLister corev1lister.PodLister
nodeLister corev1lister.NodeLister
}
@@ -34,7 +34,7 @@ func NewHandler(
cli kubernetes.Interface,
cfg *config.Config,
mem storage.Storage,
- alertManager *alertmanager.AlertManager) Handler {
+ alertManager *alert.AlertManager) Handler {
// Order is important
podFilters := []filter.Filter{
filter.NamespaceFilter{},
diff --git a/handler/handler_test.go b/internal/handler/handler_test.go
similarity index 91%
rename from handler/handler_test.go
rename to internal/handler/handler_test.go
index b3d5d03a..827c0054 100644
--- a/handler/handler_test.go
+++ b/internal/handler/handler_test.go
@@ -4,10 +4,10 @@ import (
"regexp"
"testing"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/storage"
- "github.com/abahmed/kwatch/storage/memory"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/storage"
+ "github.com/abahmed/kwatch/internal/storage/memory"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,7 +18,7 @@ func TestNewHandler(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
assert.NotNil(t, h)
@@ -28,7 +28,7 @@ func TestProcessPodNilObject(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
assert.NoError(t, h.ProcessPodObject(nil, false))
@@ -38,7 +38,7 @@ func TestProcessPodDeleted(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -58,7 +58,7 @@ func TestProcessNodeNilObject(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
assert.NoError(t, h.ProcessNodeObject(nil, false))
@@ -68,7 +68,7 @@ func TestProcessNodeDeleted(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -89,7 +89,7 @@ func TestProcessNodeNotReadyNoAlert(t *testing.T) {
IgnoreNodeMessages: []string{"specific message"},
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -116,7 +116,7 @@ func TestProcessNodeReadyRecovery(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
mem.AddNode("test-node")
@@ -144,7 +144,7 @@ func TestProcessNodeNotReadyAlert(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -173,7 +173,7 @@ func TestProcessNodeNotReadyWithIgnoredMessage(t *testing.T) {
IgnoreNodeMessages: []string{"draining"},
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -200,7 +200,7 @@ func TestProcessNodeAlreadyKnownNotReady(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
mem.AddNode("test-node")
@@ -229,7 +229,7 @@ func TestProcessPodWithPodIssues(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -260,7 +260,7 @@ func TestProcessPodWithContainersIssues(t *testing.T) {
MaxRecentLogLines: 10,
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -304,7 +304,7 @@ func TestProcessPodIgnoredNamespace(t *testing.T) {
ForbiddenNamespaces: []string{"kube-system"},
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -335,7 +335,7 @@ func TestProcessPodIgnoredPodName(t *testing.T) {
IgnorePodNamePatterns: []*regexp.Regexp{regexp.MustCompile("^test-.*")},
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -367,7 +367,7 @@ func TestProcessPodIgnoredContainerName(t *testing.T) {
IgnoreContainerNames: []string{"test-container"},
}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -409,7 +409,7 @@ func TestProcessPodSucceededPhase(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
@@ -430,7 +430,7 @@ func TestProcessPodCompletedStatus(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.Config{}
mem := memory.NewMemory()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
h := NewHandler(client, cfg, mem, alertMgr)
diff --git a/handler/processNode.go b/internal/handler/process_node.go
similarity index 82%
rename from handler/processNode.go
rename to internal/handler/process_node.go
index 9c743e98..128716f4 100644
--- a/handler/processNode.go
+++ b/internal/handler/process_node.go
@@ -4,9 +4,9 @@ import (
"fmt"
"strings"
- "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/klog/v2"
)
func (h *handler) ProcessNode(key string, deleted bool) error {
@@ -42,18 +42,18 @@ func (h *handler) ProcessNodeObject(node *corev1.Node, deleted bool) error {
for _, c := range node.Status.Conditions {
if c.Type == corev1.NodeReady {
if c.Status == corev1.ConditionFalse && !h.memory.HasNode(node.Name) {
- logrus.Printf("node %s is not ready: %s", node.Name, c.Reason)
+ klog.InfoS("node is not ready", "node", node.Name, "reason", c.Reason)
// Skip alert if Reason is in IgnoreNodeReasons
for _, ignoreReason := range h.config.IgnoreNodeReasons {
if c.Reason == ignoreReason {
- logrus.Debugf("Skipping Notify for node %s due to ignored reason: %s", node.Name, c.Reason)
+ klog.V(4).InfoS("Skipping Notify for node due to ignored reason", "node", node.Name, "reason", c.Reason)
return nil
}
}
// Skip alert if Message matches in IgnoreNodeMessages
for _, ignoreMessage := range h.config.IgnoreNodeMessages {
if strings.Contains(c.Message, ignoreMessage) {
- logrus.Debugf("Skipping Notify for node %s due to ignored message: %s", node.Name, c.Message)
+ klog.V(4).InfoS("Skipping Notify for node due to ignored message", "node", node.Name, "message", c.Message)
return nil
}
}
diff --git a/handler/processPod.go b/internal/handler/process_pod.go
similarity index 88%
rename from handler/processPod.go
rename to internal/handler/process_pod.go
index 1f3af5a8..6e9a2b13 100644
--- a/handler/processPod.go
+++ b/internal/handler/process_pod.go
@@ -3,8 +3,8 @@ package handler
import (
"fmt"
- "github.com/abahmed/kwatch/filter"
- "github.com/abahmed/kwatch/util"
+ "github.com/abahmed/kwatch/internal/filter"
+ "github.com/abahmed/kwatch/internal/k8s"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/client-go/tools/cache"
@@ -51,7 +51,7 @@ func (h *handler) ProcessPodObject(pod *corev1.Pod, deleted bool) error {
EvType: "ADDED",
}
- podEvents, err := util.GetPodEvents(ctx.Client, ctx.Pod.Name, ctx.Pod.Namespace)
+ podEvents, err := k8s.GetPodEvents(ctx.Client, ctx.Pod.Name, ctx.Pod.Namespace)
if err != nil {
return fmt.Errorf(
"failed to get events for pod %s(%s): %w",
diff --git a/health/health.go b/internal/health/health.go
similarity index 85%
rename from health/health.go
rename to internal/health/health.go
index bb4d4a03..1c6c810a 100644
--- a/health/health.go
+++ b/internal/health/health.go
@@ -7,8 +7,8 @@ import (
"strconv"
"time"
- "github.com/abahmed/kwatch/config"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/config"
+ "k8s.io/klog/v2"
)
type HealthServer struct {
@@ -30,7 +30,7 @@ func NewHealthServer(cfg config.HealthCheck) *HealthServer {
func (h *HealthServer) Start(ctx context.Context) error {
if !h.enabled {
- logrus.Debug("health check is disabled")
+ klog.V(4).InfoS("health check is disabled")
return nil
}
@@ -46,9 +46,9 @@ func (h *HealthServer) Start(ctx context.Context) error {
}
go func() {
- logrus.Infof("starting health check server on port %d", h.port)
+ klog.InfoS("starting health check server", "port", h.port)
if err := h.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- logrus.Errorf("health check server error: %v", err)
+ klog.ErrorS(err, "health check server error")
}
}()
diff --git a/health/health_test.go b/internal/health/health_test.go
similarity index 98%
rename from health/health_test.go
rename to internal/health/health_test.go
index a06a8646..2148b0ff 100644
--- a/health/health_test.go
+++ b/internal/health/health_test.go
@@ -7,7 +7,7 @@ import (
"net/http/httptest"
"testing"
- "github.com/abahmed/kwatch/config"
+ "github.com/abahmed/kwatch/internal/config"
"github.com/stretchr/testify/assert"
)
diff --git a/util/http.go b/internal/k8s/http.go
similarity index 96%
rename from util/http.go
rename to internal/k8s/http.go
index a88f6431..c12dc80b 100644
--- a/util/http.go
+++ b/internal/k8s/http.go
@@ -1,4 +1,4 @@
-package util
+package k8s
import (
"net/http"
diff --git a/util/util.go b/internal/k8s/util.go
similarity index 90%
rename from util/util.go
rename to internal/k8s/util.go
index 8dfb1653..02937c76 100644
--- a/util/util.go
+++ b/internal/k8s/util.go
@@ -1,4 +1,4 @@
-package util
+package k8s
import (
"context"
@@ -9,10 +9,10 @@ import (
"strings"
"time"
- "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
+ "k8s.io/klog/v2"
)
// GetPodEventsStr returns formatted events as a string for specified pod
@@ -77,12 +77,12 @@ func GetPodContainerLogs(
// get logs
logs, err := getContainerLogs(c, name, namespace, &options)
if err != nil {
- logrus.Warnf(
- "failed to get logs for container %s in pod %s@%s: %s",
- name,
- container,
- namespace,
- err.Error())
+ klog.InfoS(
+ "failed to get logs for container",
+ "name", name,
+ "container", container,
+ "namespace", namespace,
+ "error", err.Error())
// try to decode response
var status metav1.Status
@@ -91,12 +91,12 @@ func GetPodContainerLogs(
return status.Message
}
- logrus.Warnf(
- "failed to parse logs for container %s in pod %s@%s: %s",
- name,
- container,
- namespace,
- parseErr.Error())
+ klog.InfoS(
+ "failed to parse logs for container",
+ "name", name,
+ "container", container,
+ "namespace", namespace,
+ "error", parseErr.Error())
}
return string(logs)
@@ -184,12 +184,6 @@ func RandomString(n int) string {
// SetLogFormatter sets the log formatter based on the provided format string
func SetLogFormatter(formatter string) {
- switch formatter {
- case "json":
- logrus.SetFormatter(&logrus.JSONFormatter{})
- default:
- logrus.SetFormatter(&logrus.TextFormatter{})
- }
}
// GetNamespace returns the namespace where kwatch is running.
diff --git a/util/util_test.go b/internal/k8s/util_test.go
similarity index 99%
rename from util/util_test.go
rename to internal/k8s/util_test.go
index 699c4237..ae165976 100644
--- a/util/util_test.go
+++ b/internal/k8s/util_test.go
@@ -1,4 +1,4 @@
-package util
+package k8s
import (
"errors"
diff --git a/pvcmonitor/checkUsage.go b/internal/pvc/check_usage.go
similarity index 84%
rename from pvcmonitor/checkUsage.go
rename to internal/pvc/check_usage.go
index c373d611..22986aa4 100644
--- a/pvcmonitor/checkUsage.go
+++ b/internal/pvc/check_usage.go
@@ -1,10 +1,10 @@
-package pvcmonitor
+package pvc
import (
"fmt"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type PvcUsage struct {
@@ -16,9 +16,9 @@ type PvcUsage struct {
}
func (p *PvcMonitor) checkUsage() {
- nodes, err := util.GetNodes(p.client)
+ nodes, err := k8s.GetNodes(p.client)
if err != nil {
- logrus.Errorf("pvc monitor: failed to get nodes %s", err.Error())
+ klog.ErrorS(err, "pvc monitor: failed to get nodes")
return
}
diff --git a/pvcmonitor/getUsage.go b/internal/pvc/get_usage.go
similarity index 83%
rename from pvcmonitor/getUsage.go
rename to internal/pvc/get_usage.go
index f4e035f6..84133f4e 100644
--- a/pvcmonitor/getUsage.go
+++ b/internal/pvc/get_usage.go
@@ -1,10 +1,10 @@
-package pvcmonitor
+package pvc
import (
"encoding/json"
- "github.com/abahmed/kwatch/util"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/k8s"
+ "k8s.io/klog/v2"
)
type SummaryResponse struct {
@@ -32,7 +32,7 @@ type Ref struct {
func (p *PvcMonitor) getNodeUsage(nodeName string) ([]*PvcUsage, error) {
result := make([]*PvcUsage, 0)
- summaryResponse, err := util.GetNodeSummary(p.client, nodeName)
+ summaryResponse, err := k8s.GetNodeSummary(p.client, nodeName)
if err != nil {
return result, err
@@ -51,15 +51,14 @@ func (p *PvcMonitor) getNodeUsage(nodeName string) ([]*PvcUsage, error) {
}
pvName, err :=
- util.GetPVNameFromPVC(
+ k8s.GetPVNameFromPVC(
p.client,
pod.PodRef.Namespace,
vol.PvcRef.Name)
if err != nil {
- logrus.Errorf(
- "failed to get pv name for pvc %s: %s",
- vol.PvcRef.Name,
- err.Error())
+ klog.ErrorS(err,
+ "failed to get pv name for pvc",
+ "pvc", vol.PvcRef.Name)
continue
}
diff --git a/pvcmonitor/pvc.go b/internal/pvc/pvc.go
similarity index 75%
rename from pvcmonitor/pvc.go
rename to internal/pvc/pvc.go
index 9be69e01..ee348137 100644
--- a/pvcmonitor/pvc.go
+++ b/internal/pvc/pvc.go
@@ -1,19 +1,19 @@
-package pvcmonitor
+package pvc
import (
"sync"
"time"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
"k8s.io/client-go/kubernetes"
+ "k8s.io/klog/v2"
)
type PvcMonitor struct {
client kubernetes.Interface
config *config.PvcMonitor
- alertManager *alertmanager.AlertManager
+ alertManager *alert.AlertManager
notifiedPvc map[string]bool
mu sync.RWMutex
}
@@ -21,7 +21,7 @@ type PvcMonitor struct {
func NewPvcMonitor(
client kubernetes.Interface,
config *config.PvcMonitor,
- alertManager *alertmanager.AlertManager) *PvcMonitor {
+ alertManager *alert.AlertManager) *PvcMonitor {
return &PvcMonitor{
client: client,
config: config,
@@ -58,7 +58,7 @@ func (p *PvcMonitor) cleanup() {
count := len(p.notifiedPvc)
if count > 1000 {
- logrus.Debugf("pvc monitor: clearing %d stale entries from notifiedPvc cache", count)
+ klog.V(4).InfoS("pvc monitor: clearing stale entries from notifiedPvc cache", "count", count)
p.notifiedPvc = make(map[string]bool)
}
}
diff --git a/pvcmonitor/pvcmonitor_test.go b/internal/pvc/pvc_test.go
similarity index 93%
rename from pvcmonitor/pvcmonitor_test.go
rename to internal/pvc/pvc_test.go
index cbca75cc..d218dcf6 100644
--- a/pvcmonitor/pvcmonitor_test.go
+++ b/internal/pvc/pvc_test.go
@@ -1,12 +1,12 @@
-package pvcmonitor
+package pvc
import (
"encoding/json"
"sync"
"testing"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
"github.com/stretchr/testify/assert"
"k8s.io/client-go/kubernetes/fake"
)
@@ -20,7 +20,7 @@ func TestNewPvcMonitor(t *testing.T) {
Threshold: 80,
Interval: 5,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
assert.NotNil(pvc)
@@ -34,7 +34,7 @@ func TestNewPvcMonitorNilConfig(t *testing.T) {
assert := assert.New(t)
client := fake.NewSimpleClientset()
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, nil, alertMgr)
assert.NotNil(pvc)
@@ -57,7 +57,7 @@ func TestStartDisabled(t *testing.T) {
cfg := &config.PvcMonitor{
Enabled: false,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
pvc.Start()
@@ -68,7 +68,7 @@ func TestCleanupUnderThreshold(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.PvcMonitor{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
@@ -86,7 +86,7 @@ func TestCleanupOverThreshold(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.PvcMonitor{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
@@ -103,7 +103,7 @@ func TestCleanupExactlyThreshold(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.PvcMonitor{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
@@ -118,7 +118,7 @@ func TestCleanupExactlyThreshold(t *testing.T) {
func TestPvcMonitorConcurrency(t *testing.T) {
client := fake.NewSimpleClientset()
cfg := &config.PvcMonitor{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
@@ -257,7 +257,7 @@ func TestCheckUsageNoNodes(t *testing.T) {
Enabled: true,
Threshold: 80,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
pvc.checkUsage()
@@ -273,7 +273,7 @@ func TestCheckUsageAlreadyNotified(t *testing.T) {
Enabled: true,
Threshold: 80,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
pvc.notifiedPvc["existing-pv"] = true
@@ -289,7 +289,7 @@ func TestCheckUsageUnderThreshold(t *testing.T) {
Enabled: true,
Threshold: 90,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
@@ -316,7 +316,7 @@ func TestCheckUsageOverThreshold(t *testing.T) {
Enabled: true,
Threshold: 80,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
pvc := NewPvcMonitor(client, cfg, alertMgr)
diff --git a/startup/startup.go b/internal/startup/startup.go
similarity index 71%
rename from startup/startup.go
rename to internal/startup/startup.go
index ab3b50db..82e92ed2 100644
--- a/startup/startup.go
+++ b/internal/startup/startup.go
@@ -3,18 +3,18 @@ package startup
import (
"context"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/state"
- "github.com/abahmed/kwatch/version"
- "github.com/sirupsen/logrus"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/state"
+ "github.com/abahmed/kwatch/internal/version"
"k8s.io/client-go/kubernetes"
+ "k8s.io/klog/v2"
)
type StartupManager struct {
stateManager *state.StateManager
- alertManager *alertmanager.AlertManager
+ alertManager *alert.AlertManager
config *config.Config
}
@@ -29,7 +29,7 @@ func NewStartupManager(
config: &config.Config{App: *appCfg},
}
- sm.alertManager = &alertmanager.AlertManager{}
+ sm.alertManager = &alert.AlertManager{}
sm.alertManager.Init(alertCfg, appCfg)
return sm
@@ -38,7 +38,7 @@ func NewStartupManager(
func (s *StartupManager) HandleStartup(ctx context.Context) error {
clusterID, err := s.stateManager.EnsureClusterID(ctx)
if err != nil {
- logrus.Warnf("failed to get/create cluster ID: %v", err)
+ klog.InfoS("failed to get/create cluster ID", "error", err)
clusterID = ""
}
@@ -56,13 +56,13 @@ func (s *StartupManager) HandleStartup(ctx context.Context) error {
}
if err := s.stateManager.MarkAsInitialized(ctx, clusterID, currentVersion); err != nil {
- logrus.Warnf("failed to mark as initialized: %v", err)
+ klog.InfoS("failed to mark as initialized", "error", err)
}
return nil
}
-func (s *StartupManager) GetAlertManager() *alertmanager.AlertManager {
+func (s *StartupManager) GetAlertManager() *alert.AlertManager {
return s.alertManager
}
diff --git a/startup/startup_test.go b/internal/startup/startup_test.go
similarity index 99%
rename from startup/startup_test.go
rename to internal/startup/startup_test.go
index c95a27d4..affc289e 100644
--- a/startup/startup_test.go
+++ b/internal/startup/startup_test.go
@@ -4,7 +4,7 @@ import (
"context"
"testing"
- "github.com/abahmed/kwatch/config"
+ "github.com/abahmed/kwatch/internal/config"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/state/retry.go b/internal/state/retry.go
similarity index 93%
rename from state/retry.go
rename to internal/state/retry.go
index 2964ecdd..13a2d2fe 100644
--- a/state/retry.go
+++ b/internal/state/retry.go
@@ -5,10 +5,10 @@ import (
"strings"
"time"
- "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
+ "k8s.io/klog/v2"
)
const (
@@ -58,7 +58,7 @@ func (r *RetryConfigMapManager) UpdateWithRetry(
return err
}
- logrus.Debugf("configmap conflict, retry %d/%d", i+1, maxRetries)
+ klog.V(4).InfoS("configmap conflict, retrying", "attempt", i+1, "maxRetries", maxRetries)
time.Sleep(retryDelay)
}
diff --git a/state/state.go b/internal/state/state.go
similarity index 97%
rename from state/state.go
rename to internal/state/state.go
index 8c6d6976..9a45f6e6 100644
--- a/state/state.go
+++ b/internal/state/state.go
@@ -5,10 +5,10 @@ import (
"time"
"github.com/google/uuid"
- "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
+ "k8s.io/klog/v2"
)
const (
@@ -90,7 +90,7 @@ func (s *StateManager) MarkAsInitialized(ctx context.Context, clusterID, version
if err != nil {
return err
}
- logrus.Infof("created state configmap with cluster ID: %s", clusterID)
+ klog.InfoS("created state configmap with cluster ID", "clusterID", clusterID)
return nil
}
diff --git a/state/state_test.go b/internal/state/state_test.go
similarity index 100%
rename from state/state_test.go
rename to internal/state/state_test.go
diff --git a/storage/memory/memory.go b/internal/storage/memory/memory.go
similarity index 97%
rename from storage/memory/memory.go
rename to internal/storage/memory/memory.go
index 1bba4563..89924e78 100644
--- a/storage/memory/memory.go
+++ b/internal/storage/memory/memory.go
@@ -3,7 +3,7 @@ package memory
import (
"sync"
- storage "github.com/abahmed/kwatch/storage"
+ storage "github.com/abahmed/kwatch/internal/storage"
)
type memory struct {
diff --git a/storage/memory/memory_test.go b/internal/storage/memory/memory_test.go
similarity index 98%
rename from storage/memory/memory_test.go
rename to internal/storage/memory/memory_test.go
index 094b962b..35fb4256 100644
--- a/storage/memory/memory_test.go
+++ b/internal/storage/memory/memory_test.go
@@ -4,7 +4,7 @@ import (
"sync"
"testing"
- storage "github.com/abahmed/kwatch/storage"
+ storage "github.com/abahmed/kwatch/internal/storage"
)
func TestMemory(t *testing.T) {
diff --git a/storage/storage.go b/internal/storage/storage.go
similarity index 100%
rename from storage/storage.go
rename to internal/storage/storage.go
diff --git a/upgrader/upgrader.go b/internal/upgrader/upgrader.go
similarity index 79%
rename from upgrader/upgrader.go
rename to internal/upgrader/upgrader.go
index 000356db..e68140d3 100644
--- a/upgrader/upgrader.go
+++ b/internal/upgrader/upgrader.go
@@ -5,13 +5,13 @@ import (
"fmt"
"time"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/state"
- "github.com/abahmed/kwatch/version"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/constant"
+ "github.com/abahmed/kwatch/internal/state"
+ "github.com/abahmed/kwatch/internal/version"
"github.com/google/go-github/v41/github"
- "github.com/sirupsen/logrus"
+ "k8s.io/klog/v2"
)
type GitHubReleaseChecker interface {
@@ -43,7 +43,7 @@ type Upgrader struct {
func NewUpgrader(
config *config.Upgrader,
- alertManager *alertmanager.AlertManager,
+ alertManager *alert.AlertManager,
stateManager *state.StateManager,
) *Upgrader {
return &Upgrader{
@@ -90,12 +90,12 @@ func (u *Upgrader) checkRelease() {
"abahmed",
"kwatch")
if err != nil {
- logrus.Warnf("failed to get latest release: %s", err.Error())
+ klog.InfoS("failed to get latest release", "error", err.Error())
return
}
if r.TagName == nil {
- logrus.Warnf("failed to get release tag: %+v", r)
+ klog.InfoS("failed to get release tag", "release", r)
return
}
@@ -106,9 +106,9 @@ func (u *Upgrader) checkRelease() {
if u.stateManager != nil {
notifiedVersion := u.stateManager.GetNotifiedVersion(ctx)
if notifiedVersion == *r.TagName {
- logrus.Debugf(
- "already notified about version %s, skipping",
- *r.TagName)
+ klog.V(4).InfoS(
+ "already notified about version, skipping",
+ "version", *r.TagName)
return
}
}
@@ -117,7 +117,7 @@ func (u *Upgrader) checkRelease() {
if u.stateManager != nil {
if err := u.stateManager.SetNotifiedVersion(ctx, *r.TagName); err != nil {
- logrus.Warnf("failed to set notified version: %v", err)
+ klog.InfoS("failed to set notified version", "error", err)
}
}
}
diff --git a/upgrader/upgrader_test.go b/internal/upgrader/upgrader_test.go
similarity index 88%
rename from upgrader/upgrader_test.go
rename to internal/upgrader/upgrader_test.go
index c71886a6..8ca9558e 100644
--- a/upgrader/upgrader_test.go
+++ b/internal/upgrader/upgrader_test.go
@@ -5,10 +5,10 @@ import (
"errors"
"testing"
- "github.com/abahmed/kwatch/alertmanager"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/state"
- "github.com/abahmed/kwatch/version"
+ "github.com/abahmed/kwatch/internal/alert"
+ "github.com/abahmed/kwatch/internal/config"
+ "github.com/abahmed/kwatch/internal/state"
+ "github.com/abahmed/kwatch/internal/version"
"github.com/google/go-github/v41/github"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -50,7 +50,7 @@ func TestNewUpgrader(t *testing.T) {
assert := assert.New(t)
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -64,7 +64,7 @@ func TestNewUpgraderNilStateManager(t *testing.T) {
assert := assert.New(t)
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
u := NewUpgrader(upgraderConfig, alertMgr, nil)
assert.NotNil(u)
@@ -77,7 +77,7 @@ func TestCheckUpdatesDisabled(t *testing.T) {
upgraderConfig := &config.Upgrader{
DisableUpdateCheck: true,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -90,7 +90,7 @@ func TestUpgraderFields(t *testing.T) {
upgraderConfig := &config.Upgrader{
DisableUpdateCheck: true,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -114,7 +114,7 @@ func TestUpgraderWithDisabledConfig(t *testing.T) {
upgraderConfig := &config.Upgrader{
DisableUpdateCheck: true,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -128,7 +128,7 @@ func TestUpgraderWithEnabledConfig(t *testing.T) {
upgraderConfig := &config.Upgrader{
DisableUpdateCheck: false,
}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -140,7 +140,7 @@ func TestUpgraderConfigDefaults(t *testing.T) {
assert := assert.New(t)
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
@@ -151,7 +151,7 @@ func TestUpgraderConfigDefaults(t *testing.T) {
func TestUpgraderNilConfigNilStateManager(t *testing.T) {
assert := assert.New(t)
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
u := NewUpgrader(nil, alertMgr, nil)
assert.NotNil(u)
@@ -163,7 +163,7 @@ func TestUpgraderReuseStateManager(t *testing.T) {
assert := assert.New(t)
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
sharedStateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
u1 := NewUpgrader(upgraderConfig, alertMgr, sharedStateMgr)
@@ -180,7 +180,7 @@ func TestUpgraderStateManager(t *testing.T) {
client := fake.NewSimpleClientset()
stateMgr := state.NewStateManager(client, "kwatch")
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
assert.NotNil(u)
@@ -208,7 +208,7 @@ func TestUpgraderGetNotifiedVersion(t *testing.T) {
stateMgr := state.NewStateManager(client, namespace)
upgraderConfig := &config.Upgrader{}
- alertMgr := &alertmanager.AlertManager{}
+ alertMgr := &alert.AlertManager{}
u := NewUpgrader(upgraderConfig, alertMgr, stateMgr)
assert.NotNil(u)
@@ -220,7 +220,7 @@ func TestCheckReleaseGitHubError(t *testing.T) {
mockGithub.On("GetLatestRelease", mock.Anything, "abahmed", "kwatch").
Return(nil, nil, errors.New("rate limit exceeded"))
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, nil)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, nil)
u.SetGitHubClient(mockGithub)
u.checkRelease()
@@ -233,7 +233,7 @@ func TestCheckReleaseNilTagName(t *testing.T) {
mockGithub.On("GetLatestRelease", mock.Anything, "abahmed", "kwatch").
Return(&github.RepositoryRelease{}, nil, nil)
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, nil)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, nil)
u.SetGitHubClient(mockGithub)
u.checkRelease()
@@ -247,7 +247,7 @@ func TestCheckReleaseSameVersion(t *testing.T) {
mockGithub.On("GetLatestRelease", mock.Anything, "abahmed", "kwatch").
Return(&github.RepositoryRelease{TagName: ¤tVersion}, nil, nil)
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, nil)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, nil)
u.SetGitHubClient(mockGithub)
u.checkRelease()
@@ -276,7 +276,7 @@ func TestCheckReleaseAlreadyNotified(t *testing.T) {
stateMgr := state.NewStateManager(client, "kwatch")
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, stateMgr)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, stateMgr)
u.SetGitHubClient(mockGithub)
u.checkRelease()
@@ -295,7 +295,7 @@ func TestCheckReleaseNewVersionNotifies(t *testing.T) {
stateMgr := state.NewStateManager(fake.NewSimpleClientset(), "kwatch")
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, stateMgr)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, stateMgr)
u.SetGitHubClient(mockGithub)
u.SetAlertManager(mockAlert)
@@ -328,7 +328,7 @@ func TestCheckReleaseNewVersionSetsState(t *testing.T) {
stateMgr := state.NewStateManager(client, "kwatch")
- u := NewUpgrader(&config.Upgrader{}, &alertmanager.AlertManager{}, stateMgr)
+ u := NewUpgrader(&config.Upgrader{}, &alert.AlertManager{}, stateMgr)
u.SetGitHubClient(mockGithub)
u.SetAlertManager(mockAlert)
diff --git a/version/version.go b/internal/version/version.go
similarity index 100%
rename from version/version.go
rename to internal/version/version.go
diff --git a/version/version_test.go b/internal/version/version_test.go
similarity index 100%
rename from version/version_test.go
rename to internal/version/version_test.go
diff --git a/main.go b/main.go
deleted file mode 100644
index 5b864e6d..00000000
--- a/main.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package main
-
-import (
- "context"
- "fmt"
- "os"
- "os/signal"
- "syscall"
-
- "github.com/abahmed/kwatch/client"
- "github.com/abahmed/kwatch/config"
- "github.com/abahmed/kwatch/constant"
- "github.com/abahmed/kwatch/controller"
- "github.com/abahmed/kwatch/handler"
- "github.com/abahmed/kwatch/health"
- "github.com/abahmed/kwatch/pvcmonitor"
- "github.com/abahmed/kwatch/startup"
- "github.com/abahmed/kwatch/storage/memory"
- "github.com/abahmed/kwatch/upgrader"
- "github.com/abahmed/kwatch/util"
- "github.com/abahmed/kwatch/version"
- "github.com/sirupsen/logrus"
-)
-
-func main() {
- cfg, err := config.LoadConfig()
- if err != nil {
- logrus.Fatalf("failed to load config: %s", err.Error())
- }
- util.SetLogFormatter(cfg.App.LogFormatter)
-
- logrus.Info(fmt.Sprintf(constant.WelcomeMsg, version.Short()))
-
- k8sClient := client.Create(&cfg.App)
-
- sm := startup.NewStartupManager(
- k8sClient,
- util.GetNamespace(),
- cfg.Alert,
- &cfg.App,
- )
- sm.HandleStartup(context.Background())
-
- healthServer := health.NewHealthServer(cfg.HealthCheck)
- healthServer.Start(context.Background())
-
- upgrader := upgrader.NewUpgrader(&cfg.Upgrader, sm.GetAlertManager(), sm.GetStateManager())
- go upgrader.CheckUpdates()
-
- pvcMonitor := pvcmonitor.NewPvcMonitor(k8sClient, &cfg.PvcMonitor, sm.GetAlertManager())
- go pvcMonitor.Start()
-
- h := handler.NewHandler(
- k8sClient,
- cfg,
- memory.NewMemory(),
- sm.GetAlertManager(),
- )
-
- ctrl, cleanup := controller.New(k8sClient, cfg, h)
- defer cleanup()
-
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- go func() {
- if err := ctrl.Run(ctx, 1); err != nil {
- logrus.Fatalf("controller error: %s", err.Error())
- }
- }()
-
- sigCh := make(chan os.Signal, 1)
- signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
- <-sigCh
-
- logrus.Info("shutting down gracefully...")
- cancel()
- healthServer.Stop(context.Background())
- os.Exit(0)
-}
From 8d418c1eb575996adcd5384df10cfece60eb5864 Mon Sep 17 00:00:00 2001
From: Abdelrahman Ahmed
Date: Mon, 30 Mar 2026 23:17:18 +0200
Subject: [PATCH 2/3] fix: interpolate version in startup notification message
---
internal/startup/startup.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/internal/startup/startup.go b/internal/startup/startup.go
index 82e92ed2..9e9cecbf 100644
--- a/internal/startup/startup.go
+++ b/internal/startup/startup.go
@@ -2,6 +2,7 @@ package startup
import (
"context"
+ "fmt"
"github.com/abahmed/kwatch/internal/alert"
"github.com/abahmed/kwatch/internal/config"
@@ -52,7 +53,7 @@ func (s *StartupManager) HandleStartup(ctx context.Context) error {
if sendNotification {
s.alertManager.Notify(
- constant.WelcomeMsg)
+ fmt.Sprintf(constant.WelcomeMsg, currentVersion))
}
if err := s.stateManager.MarkAsInitialized(ctx, clusterID, currentVersion); err != nil {
From db8446e39389ca1ce6ea4677c4d7050b31a5e5d6 Mon Sep 17 00:00:00 2001
From: Abdelrahman Ahmed
Date: Tue, 31 Mar 2026 00:31:44 +0200
Subject: [PATCH 3/3] fix: use json.Marshal to fix CodeQL security alert in
matrix
---
internal/alert/matrix/matrix.go | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/internal/alert/matrix/matrix.go b/internal/alert/matrix/matrix.go
index db207571..17c41555 100644
--- a/internal/alert/matrix/matrix.go
+++ b/internal/alert/matrix/matrix.go
@@ -2,6 +2,7 @@ package matrix
import (
"bytes"
+ "encoding/json"
"fmt"
"io"
"net/http"
@@ -72,15 +73,24 @@ func (m *Matrix) SendEvent(e *event.Event) error {
func (m *Matrix) sendAPI(formattedMsg string) error {
plainMsg := stripHtmlRegex(formattedMsg)
- msg := fmt.Sprintf(`{
- "msgtype": "m.text",
- "format": "org.matrix.custom.html",
- "body": "%s",
- "formatted_body": "%s"
- }`,
- k8s.JsonEscape(plainMsg),
- k8s.JsonEscape(formattedMsg),
- )
+
+ payload := struct {
+ Msgtype string `json:"msgtype"`
+ Format string `json:"format"`
+ Body string `json:"body"`
+ FormattedBody string `json:"formatted_body"`
+ }{
+ Msgtype: "m.text",
+ Format: "org.matrix.custom.html",
+ Body: plainMsg,
+ FormattedBody: formattedMsg,
+ }
+
+ msgBytes, err := json.Marshal(payload)
+ if err != nil {
+ return err
+ }
+
request, err := http.NewRequest(
http.MethodPut,
fmt.Sprintf(
@@ -91,7 +101,7 @@ func (m *Matrix) sendAPI(formattedMsg string) error {
k8s.RandomString(24),
url.QueryEscape(m.accessToken),
),
- bytes.NewBuffer([]byte(msg)),
+ bytes.NewBuffer(msgBytes),
)
if err != nil {
return err