forked from kube-ns-suspender/kube-ns-suspender
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
174 lines (152 loc) · 6.33 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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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/kedacore/keda/v2/pkg/generated/clientset/versioned/typed/keda/v1alpha1"
"github.com/rs/zerolog/log"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/rds"
_ "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")
fs.IntVar(&opt.WatchListSize, "watchlist-size", 512, "Size of the watchlist containing namespaces waiting to be handled")
fs.BoolVar(&opt.KedaEnabled, "keda-enabled", false, "Enable pausing of Keda.sh scaledobjects")
fs.BoolVar(&opt.AwsRdsEnabled, "rds-enabled", false, "Enable stop/start of associated AWS RDS clusters")
fs.StringVar(&opt.AwsRdsNamespaceTag, "rds-namespace-tag", "Namespace", "Tag key on AWS RDS clusters identifying associated namespace")
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("watchlist size: %d", eng.Options.WatchListSize)
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))
// create the keda client
kedaclient := &v1alpha1.KedaV1alpha1Client{}
if eng.Options.KedaEnabled {
start = time.Now()
kedaclient, err = v1alpha1.NewForConfig(config)
if err != nil {
eng.Logger.Fatal().Err(err).Msg("cannot create the keda client")
}
eng.Logger.Info().Msgf("keda client successfully created in %s", time.Since(start))
} else {
eng.Logger.Info().Msg("keda is disabled")
}
// create the AWS SDK client
var rdsclient *rds.Client
if eng.Options.AwsRdsEnabled {
// Load the Shared AWS Configuration (~/.aws/config)
cfg, err := awsconfig.LoadDefaultConfig(context.TODO())
if err != nil {
eng.Logger.Fatal().Err(err).Msg("failed to load aws config")
}
rdsclient = rds.NewFromConfig(cfg)
}
eng.Logger.Info().Msgf("starting 'Watcher' and 'Suspender' routines")
ctx := context.Background()
go eng.Watcher(ctx, clientset)
go eng.Suspender(ctx, clientset, kedaclient, rdsclient)
// wait forever
select {}
}