This repository has been archived on 2023-11-25. You can view files and clone it, but cannot push or open issues or pull requests.
kreaper/main.go

142 lines
3.1 KiB
Go
Raw Normal View History

2022-04-13 06:06:23 +00:00
package main
import (
"context"
2022-04-13 12:34:27 +00:00
"flag"
2022-04-13 19:00:32 +00:00
"log"
"os"
"os/signal"
2022-04-13 12:34:27 +00:00
"path/filepath"
2022-04-13 19:00:32 +00:00
"strconv"
2022-04-13 12:34:27 +00:00
"time"
2022-04-13 06:06:23 +00:00
2022-04-13 19:00:32 +00:00
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
2022-04-13 06:06:23 +00:00
"k8s.io/client-go/rest"
2022-04-13 12:34:27 +00:00
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
2022-04-13 06:06:23 +00:00
"sigs.k8s.io/controller-runtime/pkg/client"
2022-04-13 12:34:27 +00:00
"github.com/baez90/kreaper/reaper"
)
2022-04-13 19:00:32 +00:00
const defaultKreaperLifetime = 5 * time.Minute
2022-04-13 12:34:27 +00:00
var (
kubeconfig string
2022-04-13 19:00:32 +00:00
dryRun bool
logLevel *zapcore.Level
kreaper = reaper.Kreaper{
2022-04-13 19:32:45 +00:00
Target: lookupEnvOr("KREAPER_TARGET", "", reaper.ParseTarget),
2022-04-13 19:00:32 +00:00
}
2022-04-13 06:06:23 +00:00
)
func main() {
2022-04-13 12:34:27 +00:00
prepareFlags()
2022-04-13 19:00:32 +00:00
setupLogging()
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
if err := run(ctx); err != nil {
cancel()
os.Exit(1)
}
}
func run(ctx context.Context) error {
logger := zap.L()
2022-04-13 12:34:27 +00:00
restCfg, err := loadRestConfig()
2022-04-13 06:06:23 +00:00
if err != nil {
2022-04-13 19:00:32 +00:00
logger.Error("Failed to get cluster config", zap.Error(err))
return err
2022-04-13 06:06:23 +00:00
}
2022-04-13 19:00:32 +00:00
if kreaper.Client, err = client.NewWithWatch(restCfg, client.Options{}); err != nil {
logger.Error("failed to prepare Kubernetes API client", zap.Error(err))
return err
2022-04-13 06:06:23 +00:00
}
2022-04-13 19:00:32 +00:00
return kreaper.Kill(ctx)
}
func setupLogging() {
cfg := zap.NewProductionConfig()
cfg.Level = zap.NewAtomicLevelAt(*logLevel)
logger, err := cfg.Build()
if err != nil {
log.Fatalf("Failed to setup logging: %v", err)
}
zap.ReplaceGlobals(logger)
2022-04-13 06:06:23 +00:00
}
2022-04-13 12:34:27 +00:00
func prepareFlags() {
2022-04-13 19:00:32 +00:00
logLevel = zap.LevelFlag("log-level", zapcore.InfoLevel, "Log level to use")
flag.Var(&kreaper.Target, "target", "Target that should be monitored")
flag.BoolVar(
&dryRun,
"dry-run",
lookupEnvOr("KREAPER_DRY_RUN", false, strconv.ParseBool),
"Don't actually delete anything but only list all found pods matching the target - env variable: KREAPER_DRY_RUN",
)
flag.DurationVar(
&kreaper.Lifetime,
"lifetime",
lookupEnvOr("KREAPER_LIFETIME", defaultKreaperLifetime, time.ParseDuration),
"Lifetime after which all matching targets will be deleted - env variable: KREAPER_LIFETIME",
)
flag.StringVar(
&kreaper.TargetNamespace,
"target-namespace",
lookupEnvOr("KREAPER_TARGET_NAMESPACE", "default", identity[string]),
"Set target namespace in which kreaper will look for pods - env variable: KREAPER_TARGET_NAMESPACE",
)
2022-04-13 20:16:58 +00:00
var kubeconfigFallback string
2022-04-13 12:34:27 +00:00
if home := homedir.HomeDir(); home != "" {
2022-04-13 20:16:58 +00:00
kubeconfigFallback = filepath.Join(home, ".kube", "config")
2022-04-13 12:34:27 +00:00
}
2022-04-13 19:00:32 +00:00
2022-04-13 20:16:58 +00:00
flag.StringVar(
&kubeconfig,
"kubeconfig",
lookupEnvOr("KUBECONFIG", kubeconfigFallback, identity[string]),
"absolute path to the kubeconfig file",
)
2022-04-13 19:00:32 +00:00
flag.Parse()
2022-04-13 12:34:27 +00:00
}
func loadRestConfig() (cfg *rest.Config, err error) {
if cfg, err = rest.InClusterConfig(); err == nil {
return cfg, nil
}
return clientcmd.BuildConfigFromFlags("", kubeconfig)
}
2022-04-13 19:00:32 +00:00
2022-05-13 14:16:28 +00:00
//nolint:nolintlint // false postivie
//nolint:ireturn // false positive
2022-04-13 19:00:32 +00:00
func lookupEnvOr[T any](envKey string, fallback T, parse func(envVal string) (T, error)) T {
envVal := os.Getenv(envKey)
if envVal == "" {
return fallback
}
if parsed, err := parse(envVal); err != nil {
return fallback
} else {
return parsed
}
}
2022-05-13 14:16:28 +00:00
//nolint:nolintlint // false postivie
//nolint:ireturn // false positive
2022-04-13 19:00:32 +00:00
func identity[T any](in T) (T, error) {
return in, nil
}