forked from kube-ns-suspender/kube-ns-suspender
-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
140 lines (122 loc) · 4.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"os"
"time"
"github.com/namsral/flag"
"github.com/govirtuo/kube-ns-suspender/engine"
"github.com/govirtuo/kube-ns-suspender/metrics"
"github.com/govirtuo/kube-ns-suspender/pprof"
"github.com/govirtuo/kube-ns-suspender/webui"
"github.com/rs/zerolog/log"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
)
var (
// Version holds the build version
Version string
// BuildDate holds the build date
BuildDate string
)
func main() {
var opt engine.Options
var err error
fs := flag.NewFlagSetWithEnvPrefix(os.Args[0], "KUBE_NS_SUSPENDER", 0)
fs.StringVar(&opt.LogLevel, "log-level", "debug", "Log level")
fs.StringVar(&opt.TZ, "timezone", "Europe/Paris", "Timezone to use")
fs.StringVar(&opt.Prefix, "prefix", "kube-ns-suspender/", "Prefix to use for annotations")
fs.StringVar(&opt.ControllerName, "controller-name", "kube-ns-suspender", "Unique name of the controller")
fs.StringVar(&opt.RunningDuration, "running-duration", "4h", "Running duration")
fs.IntVar(&opt.WatcherIdle, "watcher-idle", 15, "Watcher idle duration (in seconds)")
fs.BoolVar(&opt.NoKubeWarnings, "no-kube-warnings", false, "Disable Kubernetes warnings")
fs.BoolVar(&opt.HumanLogs, "human", false, "Disable JSON logging")
fs.BoolVar(&opt.EmbeddedUI, "ui-embedded", false, "Start UI in background")
fs.BoolVar(&opt.WebUIOnly, "ui-only", false, "Start UI only")
fs.BoolVar(&opt.PProf, "pprof", false, "Start pprof server")
fs.StringVar(&opt.PProfAddr, "pprof-addr", ":4455", "Address and port to use with pprof")
fs.StringVar(&opt.SlackChannelName, "slack-channel-name", "", "Name of the help Slack channel in the UI bug page")
fs.StringVar(&opt.SlackChannelLink, "slack-channel-link", "", "Link of the helm Slack channel in the UI bug page")
if err := fs.Parse(os.Args[1:]); err != nil {
log.Fatal().Err(err).Msg("cannot parse flags")
}
// set the local timezone
time.Local, err = time.LoadLocation(opt.TZ)
if err != nil {
log.Fatal().Err(err).Msg("cannot load timezone")
}
// create the engine
start := time.Now()
eng, err := engine.New(opt)
if err != nil {
log.Fatal().Err(err).Msg("cannot create new engine")
}
eng.Logger.Info().Msgf("engine successfully created in %s", time.Since(start))
eng.Logger.Info().Msgf("kube-ns-suspender version '%s' (built %s)", Version, BuildDate)
if eng.Options.PProf {
s, err := pprof.New(eng.Options.PProfAddr)
if err != nil {
eng.Logger.Fatal().Err(err).Msg("cannot start pprof")
}
eng.Logger.Info().Msgf("starting pprof on %s", eng.Options.PProfAddr)
go s.Run()
}
// start web ui
if eng.Options.EmbeddedUI || eng.Options.WebUIOnly {
go func() {
uiLogger := eng.Logger.With().Str("routine", "webui").Logger()
if err := webui.Start(uiLogger, "8080",
eng.Options.Prefix, eng.Options.ControllerName, Version, BuildDate, opt.SlackChannelName, opt.SlackChannelLink); err != nil {
uiLogger.Fatal().Err(err).Msg("web UI failed")
}
}()
eng.Logger.Info().Msg("web UI successfully created")
if eng.Options.WebUIOnly {
eng.Logger.Info().Msg("starting web UI only")
// if we want only the webui, we have to wait here forever after the creation
select {}
}
}
eng.Logger.Debug().Msgf("timezone: %s", time.Local.String())
eng.Logger.Debug().Msgf("watcher idle: %s", time.Duration(eng.Options.WatcherIdle)*time.Second)
eng.Logger.Debug().Msgf("running duration: %s", eng.RunningDuration)
eng.Logger.Debug().Msgf("log level: %s", eng.Options.LogLevel)
eng.Logger.Debug().Msgf("json logging: %v", !eng.Options.HumanLogs)
eng.Logger.Debug().Msgf("controller name: %v", eng.Options.ControllerName)
eng.Logger.Debug().Msgf("annotations prefix: %v", eng.Options.Prefix)
// create metrics server
start = time.Now()
eng.MetricsServ = *metrics.Init()
// start metrics server
go func() {
if err := eng.MetricsServ.Start(); err != nil {
eng.Logger.Fatal().Err(err).Msg("metrics server failed")
}
}()
eng.Logger.Info().Msgf("metrics server successfully created in %s", time.Since(start))
// create the in-cluster config
start = time.Now()
config, err := rest.InClusterConfig()
if err != nil {
eng.Logger.Fatal().Err(err).Msg("cannot create in-cluster configuration")
}
eng.Logger.Info().Msgf("in-cluster configuration successfully created in %s", time.Since(start))
// disable k8s warnings
if eng.Options.NoKubeWarnings {
config.WarningHandler = rest.NoWarnings{}
eng.Logger.Info().Msgf("Kubernetes warnings disabled")
}
// create the clientset
start = time.Now()
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
eng.Logger.Fatal().Err(err).Msg("cannot create the clientset")
}
eng.Logger.Info().Msgf("clientset successfully created in %s", time.Since(start))
eng.Logger.Info().Msgf("starting 'Watcher' and 'Suspender' routines")
ctx := context.Background()
go eng.Watcher(ctx, clientset)
go eng.Suspender(ctx, clientset)
// wait forever
select {}
}