-
Notifications
You must be signed in to change notification settings - Fork 13
/
main.go
147 lines (124 loc) · 4.3 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
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/mercari/certificate-expiry-monitor-controller/config"
"github.com/mercari/certificate-expiry-monitor-controller/controller"
logging "github.com/mercari/certificate-expiry-monitor-controller/log"
"github.com/mercari/certificate-expiry-monitor-controller/notifier"
"github.com/mercari/certificate-expiry-monitor-controller/notifier/log"
"github.com/mercari/certificate-expiry-monitor-controller/notifier/slack"
synthetics "github.com/mercari/certificate-expiry-monitor-controller/synthetics/datadog"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
os.Exit(runMain())
}
func runMain() int {
// Parse configurations from environment variables
var env config.Env
if err := env.ParseEnv(); err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to parse environement variables: %s\n", err.Error())
return 1
}
// Setup clientSet from configuration.
clientSet, err := newClientSet(env.KubeconfigPath)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create clientSet: %s\n", err.Error())
return 1
}
// Setup notifiers from configuration.
// If user specify unsupported notifier name, program returns exit code `1`.
notifiers := make([]notifier.Notifier, len(env.Notifiers))
for i, name := range env.Notifiers {
switch name {
case slack.String():
sl, err := slack.NewNotifier(env.SlackToken, env.SlackChannel)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create slack notifier: %s\n", err.Error())
return 1
}
notifiers[i] = sl
case log.String():
logger, err := logging.NewLogger(log.AlertLogLevel())
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create log notifier: %s\n", err.Error())
return 1
}
notifiers[i] = log.NewNotifier(logger)
default:
fmt.Fprintf(os.Stderr, "[ERROR] Unexpected notifier name: %s\n", name)
return 1
}
}
// Setup logger that wrapped zap.Logger to use common settings.
logger, err := logging.NewLogger(env.LogLevel)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create logger: %s\n", err.Error())
return 1
}
// Create a new synthetics testManager instance
testManager := &synthetics.TestManager{}
if env.TestManager {
testManager, err = synthetics.NewTestManager(env.DatadogAPIKey, env.DatadogAppKey)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create testManager: %s\n", err.Error())
return 1
}
testManager.Logger = logger
testManager.CheckInterval = env.CheckInterval
testManager.AlertMessage = env.AlertMessage
testManager.Tags = env.Tags
testManager.DefaultTag = env.DefaultTag
testManager.AdditionalEndpoints = env.AdditionalEndpoints
testManager.DefaultLocations = env.DefaultLocations
// Set control flag to prevent running the synthetics logic in the controller when feature-gated
testManager.Enabled = true
}
// Create new controller instance.
controller, err := controller.NewController(logger, clientSet, env.VerifyInterval, env.AlertThreshold, notifiers, testManager)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] Failed to create controller: %s\n", err.Error())
return 1
}
// When controller receives SIGINT or SIGTERM,
// handleSignal goroutine triggers stopCh to terminate controller.
stopCh := make(chan struct{}, 1)
go handleSignal(stopCh)
controller.Run(stopCh)
return 0
}
// Create new Kubernetes's clientSet.
// When configured env.KubeconfigPath, read config from env.KubeconfigPath.
// When not configured env.KubeconfigPath, read internal cluster config.
func newClientSet(kubeconfigPath string) (*kubernetes.Clientset, error) {
var err error
var config *rest.Config
if kubeconfigPath == "" {
config, err = rest.InClusterConfig()
} else {
config, err = clientcmd.BuildConfigFromFlags("", kubeconfigPath)
}
if err != nil {
return nil, err
}
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return clientSet, nil
}
// Handling syscall.SIGTERM and syscall.SIGINT
// When trap those, function send message to stopCh
func handleSignal(stopCh chan struct{}) {
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGTERM)
signal.Notify(signalCh, syscall.SIGINT)
<-signalCh
close(stopCh)
}