mirror of
https://github.com/lukaszraczylo/kportal.git
synced 2026-07-07 06:25:43 +00:00
style: Extract UI constants and refactor main view rendering (#30)
- [x] Add golangci-lint configuration with gocritic ifElseChain disabled
- [x] Rename error variables to avoid shadowing (createErr, watcherErr, watchErr, etc.)
- [x] Replace `interface{}` with `any` type alias throughout codebase
- [x] Add package-level documentation comments to all internal packages
- [x] Reorder struct fields alphabetically for consistency
- [x] Extract UI constants (terminal dimensions, column widths, colors) to constants.go
- [x] Refactor BubbleTeaUI main view rendering into smaller helper functions
- [x] Simplify nested conditionals and improve code clarity
- [x] Add `isForwardDisabled()` helper method to BubbleTeaUI
- [x] Update file permissions from 0644 to 0600 in config tests
- [x] Add `#nosec` comments and error suppression where appropriate
- [x] Improve test table struct field ordering for readability
- [x] Fix resource parsing in AddForward using strings.SplitN
- [x] Add comprehensive tests for new UI helper functions and constants
This commit is contained in:
@@ -17,10 +17,10 @@ func TestKlogWriter(t *testing.T) {
|
||||
input string
|
||||
expectedLevel string
|
||||
expectedMsg string
|
||||
description string
|
||||
loggerLevel Level
|
||||
loggerFormat Format
|
||||
shouldLog bool
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "info level log",
|
||||
@@ -162,9 +162,9 @@ func TestKlogWriter(t *testing.T) {
|
||||
func TestKlogWriterBuffering(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
description string
|
||||
writes []string
|
||||
expectCount int
|
||||
description string
|
||||
}{
|
||||
{
|
||||
name: "single complete line",
|
||||
@@ -264,7 +264,7 @@ func TestKlogWriterConcurrency(t *testing.T) {
|
||||
go func(id int) {
|
||||
for j := 0; j < numWrites; j++ {
|
||||
msg := fmt.Sprintf("I1124 12:34:56.789012 12345 test.go:123] Message from goroutine %d iteration %d\n", id, j)
|
||||
klogWriter.Write([]byte(msg))
|
||||
_, _ = klogWriter.Write([]byte(msg))
|
||||
}
|
||||
done <- true
|
||||
}(i)
|
||||
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
func TestLogrAdapter_Info(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loggerLevel Level
|
||||
logrLevel int
|
||||
message string
|
||||
keysAndValues []interface{}
|
||||
expectOutput bool
|
||||
expectContains []string
|
||||
loggerLevel Level
|
||||
logrLevel int
|
||||
expectOutput bool
|
||||
}{
|
||||
{
|
||||
name: "info log v0 with debug logger",
|
||||
@@ -109,13 +109,13 @@ func TestLogrAdapter_Info(t *testing.T) {
|
||||
|
||||
func TestLogrAdapter_Error(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loggerLevel Level
|
||||
err error
|
||||
name string
|
||||
message string
|
||||
keysAndValues []interface{}
|
||||
expectOutput bool
|
||||
expectContains []string
|
||||
loggerLevel Level
|
||||
expectOutput bool
|
||||
}{
|
||||
{
|
||||
name: "error with error object",
|
||||
@@ -179,9 +179,9 @@ func TestLogrAdapter_Error(t *testing.T) {
|
||||
func TestLogrAdapter_WithName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loggerNames []string
|
||||
message string
|
||||
expectContains string
|
||||
loggerNames []string
|
||||
}{
|
||||
{
|
||||
name: "single logger name",
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
// Package logger provides structured logging with support for text and JSON
|
||||
// output formats. It intercepts Kubernetes client-go logs and routes them
|
||||
// through the structured logger.
|
||||
//
|
||||
// The package provides both instance-based and global logging:
|
||||
//
|
||||
// // Instance-based logging
|
||||
// log := logger.New(logger.LevelInfo, logger.FormatJSON, os.Stderr)
|
||||
// log.Info("message", "key", "value")
|
||||
//
|
||||
// // Global logging (after Init)
|
||||
// logger.Init(logger.LevelInfo, logger.FormatText, os.Stderr)
|
||||
// logger.Info("message", "key", "value")
|
||||
//
|
||||
// Log levels: DEBUG < INFO < WARN < ERROR
|
||||
// Output formats: FormatText (human-readable), FormatJSON (structured)
|
||||
package logger
|
||||
|
||||
import (
|
||||
@@ -9,36 +25,50 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Level represents the logging level.
|
||||
// Higher levels include all lower levels (e.g., LevelInfo includes WARN and ERROR).
|
||||
type Level int
|
||||
|
||||
const (
|
||||
// LevelDebug is for detailed troubleshooting information.
|
||||
LevelDebug Level = iota
|
||||
// LevelInfo is for general operational information.
|
||||
LevelInfo
|
||||
// LevelWarn is for unexpected but handled situations.
|
||||
LevelWarn
|
||||
// LevelError is for failures that require attention.
|
||||
LevelError
|
||||
)
|
||||
|
||||
// Format represents the output format for log entries.
|
||||
type Format int
|
||||
|
||||
const (
|
||||
// FormatText outputs human-readable log lines.
|
||||
FormatText Format = iota
|
||||
// FormatJSON outputs structured JSON log entries.
|
||||
FormatJSON
|
||||
)
|
||||
|
||||
// Logger is a structured logger with configurable level and format.
|
||||
// It is safe for concurrent use.
|
||||
type Logger struct {
|
||||
output io.Writer
|
||||
level Level
|
||||
format Format
|
||||
output io.Writer
|
||||
mu sync.Mutex // Protects concurrent writes to output
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// logEntry represents a single log entry for JSON output.
|
||||
type logEntry struct {
|
||||
Time string `json:"time"`
|
||||
Level string `json:"level"`
|
||||
Message string `json:"message"`
|
||||
Fields map[string]interface{} `json:"fields,omitempty"`
|
||||
Fields map[string]any `json:"fields,omitempty"`
|
||||
Time string `json:"time"`
|
||||
Level string `json:"level"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// New creates a new Logger with the specified level, format, and output writer.
|
||||
// If output is nil, os.Stderr is used.
|
||||
func New(level Level, format Format, output io.Writer) *Logger {
|
||||
if output == nil {
|
||||
output = os.Stderr
|
||||
|
||||
@@ -13,13 +13,13 @@ import (
|
||||
|
||||
func TestLoggerTextFormat(t *testing.T) {
|
||||
tests := []struct {
|
||||
fields map[string]interface{}
|
||||
name string
|
||||
message string
|
||||
expectContains []string
|
||||
level Level
|
||||
logLevel Level
|
||||
message string
|
||||
fields map[string]interface{}
|
||||
expectOutput bool
|
||||
expectContains []string
|
||||
}{
|
||||
{
|
||||
name: "info logged at info level",
|
||||
@@ -138,13 +138,13 @@ func TestLoggerTextFormat(t *testing.T) {
|
||||
|
||||
func TestLoggerJSONFormat(t *testing.T) {
|
||||
tests := []struct {
|
||||
fields map[string]interface{}
|
||||
name string
|
||||
message string
|
||||
expectLevel string
|
||||
level Level
|
||||
logLevel Level
|
||||
message string
|
||||
fields map[string]interface{}
|
||||
expectOutput bool
|
||||
expectLevel string
|
||||
}{
|
||||
{
|
||||
name: "info logged at info level",
|
||||
@@ -268,12 +268,12 @@ func TestLoggerJSONFormat(t *testing.T) {
|
||||
|
||||
func TestGlobalLogger(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
initLevel Level
|
||||
initFormat Format
|
||||
logFunc func(string, ...map[string]interface{})
|
||||
name string
|
||||
message string
|
||||
expectContains string
|
||||
initLevel Level
|
||||
initFormat Format
|
||||
}{
|
||||
{
|
||||
name: "global info logger text",
|
||||
@@ -321,9 +321,9 @@ func TestGlobalLogger(t *testing.T) {
|
||||
func TestLogLevelsFiltering(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
loggerLevel Level
|
||||
logAtLevels []Level
|
||||
expectOutputs []bool
|
||||
loggerLevel Level
|
||||
}{
|
||||
{
|
||||
name: "debug level logs everything",
|
||||
@@ -387,14 +387,14 @@ func TestLoggerNilOutput(t *testing.T) {
|
||||
|
||||
func TestLevelToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
level Level
|
||||
expected string
|
||||
level Level
|
||||
}{
|
||||
{LevelDebug, "DEBUG"},
|
||||
{LevelInfo, "INFO"},
|
||||
{LevelWarn, "WARN"},
|
||||
{LevelError, "ERROR"},
|
||||
{Level(999), "UNKNOWN"},
|
||||
{level: LevelDebug, expected: "DEBUG"},
|
||||
{level: LevelInfo, expected: "INFO"},
|
||||
{level: LevelWarn, expected: "WARN"},
|
||||
{level: LevelError, expected: "ERROR"},
|
||||
{level: Level(999), expected: "UNKNOWN"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -407,8 +407,8 @@ func TestLevelToString(t *testing.T) {
|
||||
|
||||
func TestJSONFieldTypes(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fields map[string]interface{}
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "string fields",
|
||||
@@ -467,10 +467,10 @@ func TestJSONFieldTypes(t *testing.T) {
|
||||
|
||||
func TestInitWithCustomOutput(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
output io.Writer
|
||||
expectDiscard bool
|
||||
name string
|
||||
description string
|
||||
expectDiscard bool
|
||||
}{
|
||||
{
|
||||
name: "init with custom buffer",
|
||||
|
||||
Reference in New Issue
Block a user