Skip to content

Architecture

Package overview

go-libs is organized as a set of independent packages under pkg/. All packages import utils; no other cross-package imports are allowed except prometheus → k8sclient.

pkg/utils        ← foundation: display, arg parsing, debug flag, exit hook
    ↑
    ├── pkg/k8sclient    ← Kubernetes client (wraps client-go)
    │       ↑
    │       └── pkg/prometheus   ← Prometheus query client
    │
    ├── pkg/kubeconfig   ← kubeconfig YAML load/save
    ├── pkg/incrementor  ← resource.Quantity parser and arithmetic
    ├── pkg/mailer       ← SMTP email with HTML body and attachments
    ├── pkg/gdrive       ← Google Drive / Sheets via service account
    └── pkg/confluence   ← Confluence Cloud REST API

Design patterns

Builder (fluent API)

ArgParser, MailerMail, Incrementor, and Kubeconfig follow a fluent builder pattern where each setter returns *Self:

mail := mailer.NewMailerMail().
    SetTo("user@example.com").
    SetSubject("Report").
    SetBody("Hello").
    SetBodyHTML("<p>Hello</p>")

Constructor pairs

Each type has an exported constructor (NewFoo) that delegates to an unexported one (newFoo). Business logic lives in the unexported variant.

Interfaces for mocking

  • k8sclient.K8sClientIface — use in callers to allow test mocking of the Kubernetes client
  • prometheus.PrometheusIface — use in callers to allow test mocking of the Prometheus client

Thread safety

  • utils.SetDebug(bool) / utils.GetDebug() bool are backed by sync/atomic.Bool and are safe to call from multiple goroutines.
  • utils.ExitFunc is a package-level variable and is not goroutine-safe. Override it only in tests, and restore it with defer.

Key invariants

Package Invariant
kubeconfig GetConfigBytes() returns []byte(kc.Config) — the string is already valid YAML, no marshalling needed
gdrive SetCredentialsContent(*SACreds) fills missing fields with placeholder defaults and logs a warning for each
mailer MailerMail.BodyHTML — when non-empty, added as text/html alternative part via gomail.AddAlternative
k8sclient NewK8sClient("", false, false) calls ExitFunc internally when no kubeconfig is found — never call it in tests without overriding ExitFunc