Skip to content
This repository was archived by the owner on May 24, 2025. It is now read-only.

Commit a8003cf

Browse files
authored
Merge pull request #10 from sers-dev/#9RemoveGlobalVars
#9: removed global variables and replaced them by two new types
2 parents 5580a57 + 9ebb21f commit a8003cf

File tree

2 files changed

+89
-50
lines changed

2 files changed

+89
-50
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,25 @@ Environment variables needed for successful execution:
3131
by default set to 60s, so if you change the value of kubelets parameter you should use the same value plus a few seconds
3232
to trigger at `doveadm reload` after adding/changing tls secrets successfully
3333

34+
When running inside a kubernetes cluster the pod needs the following permissions via Role for the same namespace your
35+
dovecot pods run in:
36+
```
37+
rules:
38+
- apiGroups:
39+
- ""
40+
resources:
41+
- pods
42+
- secrets
43+
verbs:
44+
- list
45+
- watch
46+
- apiGroups:
47+
- ""
48+
resources:
49+
- pods/exec
50+
verbs:
51+
- create
52+
```
53+
3454
### Used Library
3555
https://github.com/kubernetes/client-go

cmd/main.go

Lines changed: 69 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,56 @@ import (
2020
"time"
2121
)
2222

23-
// variables: namespace, labels
24-
var dovecotLabels string
25-
var dovecotDirectorLabels string
26-
var dovecotDirectorContainerName string
27-
var syncFrequencyDuration int
23+
var initialDovecotPodCount int
2824

29-
var namespace string
30-
var kubeconf *rest.Config
25+
type EnvVariables struct {
26+
DovecotLabels string
27+
DovecotDirectorLabels string
28+
DovecotDirectorContainerName string
29+
Namespace string
30+
SyncFrequencyDuration int
31+
}
3132

32-
var initialDovecotPodCount int
33+
type K3sVars struct {
34+
Kubeconf *rest.Config
35+
Clientset *kubernetes.Clientset
36+
}
3337

3438
func main() {
35-
clientset, err := InClusterAuth()
39+
clientset, kubeconfig, err := InClusterAuth()
3640

3741
if clientset == nil {
38-
clientset, err = OutOfClusterAuth()
42+
clientset, kubeconfig, err = OutOfClusterAuth()
3943
}
4044
if err != nil {
4145
panic(err.Error())
4246
}
43-
dovecotDirectorLabels = os.Getenv("DOVECOT_DIRECTOR_LABELS")
44-
dovecotDirectorContainerName = os.Getenv("DOVECOT_DIRECTOR_CONTAINER_NAME")
45-
dovecotLabels = os.Getenv("DOVECOT_LABELS")
46-
namespace = os.Getenv("DOVECOT_NAMESPACE")
47+
4748
syncFrequencyDurationEnv := os.Getenv("SYNC_FREQUENCY_DURATION")
4849

49-
syncFrequencyDuration = 70
50+
syncFrequencyDuration := 70
5051
if syncFrequencyDurationEnv != "" {
5152
syncFrequencyDuration, err = strconv.Atoi(syncFrequencyDurationEnv)
5253
if err != nil {
5354
syncFrequencyDuration = 70
5455
}
5556
}
57+
envVariables := EnvVariables{
58+
DovecotLabels: os.Getenv("DOVECOT_LABELS"),
59+
DovecotDirectorLabels: os.Getenv("DOVECOT_DIRECTOR_LABELS"),
60+
DovecotDirectorContainerName: os.Getenv("DOVECOT_DIRECTOR_CONTAINER_NAME"),
61+
Namespace: os.Getenv("DOVECOT_NAMESPACE"),
62+
SyncFrequencyDuration: syncFrequencyDuration,
63+
}
5664

57-
dovecotPods := GetPodsByLabel(clientset, namespace, dovecotLabels)
65+
dovecotPods := GetPodsByLabel(clientset, envVariables.Namespace, envVariables.DovecotLabels)
5866
initialDovecotPodCount = len(dovecotPods.Items)
5967

60-
StartWatchers(clientset, namespace)
68+
k3sVars := K3sVars{
69+
Kubeconf: kubeconfig,
70+
Clientset: clientset,
71+
}
72+
StartWatchers(envVariables, k3sVars)
6173
}
6274

6375
func GetPodsByLabel(clientset *kubernetes.Clientset, namespace string, labels string) *v1.PodList {
@@ -72,16 +84,16 @@ func GetPodsByLabel(clientset *kubernetes.Clientset, namespace string, labels st
7284
return pods
7385
}
7486

75-
func ExecuteCommand(command string, podname string, namespace string, clientset *kubernetes.Clientset) error {
87+
func ExecuteCommand(command string, podname string, namespace string, containerName string, k3sVars K3sVars) error {
7688
cmd := []string{
7789
"sh",
7890
"-c",
7991
command,
8092
}
81-
req := clientset.CoreV1().RESTClient().Post().Resource("pods").Name(podname).Namespace(namespace).SubResource("exec")
93+
req := k3sVars.Clientset.CoreV1().RESTClient().Post().Resource("pods").Name(podname).Namespace(namespace).SubResource("exec")
8294
// THE FOLLOWING EXPECTS THE POD TO HAVE ONLY ONE CONTAINER IN WHICH THE COMMAND IS GOING TO BE EXECUTED
8395
option := &v1.PodExecOptions{
84-
Container: dovecotDirectorContainerName,
96+
Container: containerName,
8597
Command: cmd,
8698
Stdin: false,
8799
Stdout: true,
@@ -94,7 +106,7 @@ func ExecuteCommand(command string, podname string, namespace string, clientset
94106
scheme.ParameterCodec,
95107
)
96108

97-
exec, err := remotecommand.NewSPDYExecutor(kubeconf, "POST", req.URL())
109+
exec, err := remotecommand.NewSPDYExecutor(k3sVars.Kubeconf, "POST", req.URL())
98110
if err != nil {
99111
return err
100112
}
@@ -113,7 +125,7 @@ func ExecuteCommand(command string, podname string, namespace string, clientset
113125
return nil
114126
}
115127

116-
func handleEvent(pod *v1.Pod, clientset *kubernetes.Clientset) {
128+
func handleEvent(pod *v1.Pod, envVars EnvVariables, k3sVars K3sVars) {
117129
if initialDovecotPodCount > 1 {
118130
initialDovecotPodCount--
119131
return
@@ -126,17 +138,17 @@ func handleEvent(pod *v1.Pod, clientset *kubernetes.Clientset) {
126138

127139
for _, containerStatus := range containerStatusSlice {
128140
if containerStatus.Ready {
129-
ExecuteDoveAdm(clientset, dovecotDirectorLabels, 0)
141+
ExecuteDoveAdm(envVars, k3sVars, "pod", 0)
130142
}
131143
}
132144
}
133145
}
134146

135-
func ExecuteDoveAdm(clientset *kubernetes.Clientset, dovecotDirectorLabels string, sleeptime int) {
136-
if sleeptime != 0 {
137-
time.Sleep(time.Second * time.Duration(int64(sleeptime)))
147+
func ExecuteDoveAdm(envVars EnvVariables, k3sVars K3sVars, trigger string, sleepTime int) {
148+
if sleepTime != 0 {
149+
time.Sleep(time.Second * time.Duration(int64(sleepTime)))
138150
}
139-
podlist := GetPodsByLabel(clientset, namespace, dovecotDirectorLabels)
151+
podlist := GetPodsByLabel(k3sVars.Clientset, envVars.Namespace, envVars.DovecotDirectorLabels)
140152

141153
for _, dovecotDirectorPod := range podlist.Items {
142154
curTime := time.Now()
@@ -147,24 +159,31 @@ func ExecuteDoveAdm(clientset *kubernetes.Clientset, dovecotDirectorLabels strin
147159
err := ExecuteCommand(
148160
"doveadm reload",
149161
dovecotDirectorPod.ObjectMeta.Name,
150-
namespace,
151-
clientset)
162+
envVars.Namespace,
163+
envVars.DovecotDirectorContainerName,
164+
k3sVars)
152165

153166
if err != nil {
154167
logLevel = "error"
155168
logMessage = err.Error()
156169
}
157170

158-
log := fmt.Sprintf("{ \"level\": \"%s\", \"timestamp\": \"%s\", \"pod\": \"%s\", \"command\": \"doveadm reload\", \"message\": \"%s\" }", logLevel, formattedTime, dovecotDirectorPod.ObjectMeta.Name, logMessage)
171+
log := fmt.Sprintf("{ \"level\": \"%s\", \"timestamp\": \"%s\", \"pod\": \"%s\", \"command\": \"doveadm reload\", \"triggered-by\": \"%s\", \"message\": \"%s\" }",
172+
logLevel,
173+
formattedTime,
174+
dovecotDirectorPod.ObjectMeta.Name,
175+
trigger,
176+
logMessage,
177+
)
159178
fmt.Println(log)
160179
}
161180
}
162181

163-
func StartWatchers(clientset *kubernetes.Clientset, namespace string) {
182+
func StartWatchers(envVars EnvVariables, k3sVars K3sVars) {
164183
watchlistSecrets := cache.NewFilteredListWatchFromClient(
165-
clientset.CoreV1().RESTClient(),
184+
k3sVars.Clientset.CoreV1().RESTClient(),
166185
"secrets",
167-
namespace,
186+
envVars.Namespace,
168187
func(options *metav1.ListOptions) {},
169188
)
170189
_, controllerSecrets := cache.NewInformer(
@@ -175,23 +194,23 @@ func StartWatchers(clientset *kubernetes.Clientset, namespace string) {
175194
AddFunc: func(obj interface{}) {
176195
secret := obj.(*v1.Secret)
177196
if secret.Type == "kubernetes.io/tls" {
178-
go ExecuteDoveAdm(clientset, dovecotDirectorLabels, syncFrequencyDuration)
197+
go ExecuteDoveAdm(envVars, k3sVars, "secret", envVars.SyncFrequencyDuration)
179198
}
180199
},
181200
UpdateFunc: func(oldObj, newObj interface{}) {
182201
secret := newObj.(*v1.Secret)
183202
if secret.Type == "kubernetes.io/tls" {
184-
go ExecuteDoveAdm(clientset, dovecotDirectorLabels, syncFrequencyDuration)
203+
go ExecuteDoveAdm(envVars, k3sVars, "secret", envVars.SyncFrequencyDuration)
185204
}
186205
},
187206
},
188207
)
189208

190209
watchlistPods := cache.NewFilteredListWatchFromClient(
191-
clientset.CoreV1().RESTClient(),
210+
k3sVars.Clientset.CoreV1().RESTClient(),
192211
"pods",
193-
namespace,
194-
func(options *metav1.ListOptions) { options.LabelSelector = dovecotLabels },
212+
envVars.Namespace,
213+
func(options *metav1.ListOptions) { options.LabelSelector = envVars.DovecotLabels },
195214
)
196215

197216
_, controllerPods := cache.NewInformer(
@@ -200,10 +219,10 @@ func StartWatchers(clientset *kubernetes.Clientset, namespace string) {
200219
time.Second*0,
201220
cache.ResourceEventHandlerFuncs{
202221
AddFunc: func(obj interface{}) {
203-
handleEvent(obj.(*v1.Pod), clientset)
222+
handleEvent(obj.(*v1.Pod), envVars, k3sVars)
204223
},
205224
UpdateFunc: func(oldObj, newObj interface{}) {
206-
handleEvent(newObj.(*v1.Pod), clientset)
225+
handleEvent(newObj.(*v1.Pod), envVars, k3sVars)
207226
},
208227
},
209228
)
@@ -216,33 +235,33 @@ func StartWatchers(clientset *kubernetes.Clientset, namespace string) {
216235
}
217236
}
218237

219-
func InClusterAuth() (*kubernetes.Clientset, error) {
238+
func InClusterAuth() (*kubernetes.Clientset, *rest.Config, error) {
220239
var err error
221-
kubeconf, err = rest.InClusterConfig()
240+
kubeconf, err := rest.InClusterConfig()
222241

223242
if err != nil {
224-
return nil, nil
243+
return nil, nil, nil
225244
}
226245

227246
clientset, err := kubernetes.NewForConfig(kubeconf)
228247
if err != nil {
229248
panic(err.Error())
230249
}
231250

232-
return clientset, nil
251+
return clientset, kubeconf, nil
233252
}
234253

235-
func OutOfClusterAuth() (*kubernetes.Clientset, error) {
236-
var kubeconfig *string
254+
func OutOfClusterAuth() (*kubernetes.Clientset, *rest.Config, error) {
255+
var configPath *string
237256
if home := homedir.HomeDir(); home != "" {
238-
kubeconfig = flag.String("c", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
257+
configPath = flag.String("c", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the configPath file")
239258
} else {
240-
kubeconfig = flag.String("c", "", "absolute path to the kubeconfig file")
259+
configPath = flag.String("c", "", "absolute path to the configPath file")
241260
}
242261
flag.Parse()
243262

244263
var err error
245-
kubeconf, err = clientcmd.BuildConfigFromFlags("", *kubeconfig)
264+
kubeconf, err := clientcmd.BuildConfigFromFlags("", *configPath)
246265
if err != nil {
247266
panic(err.Error())
248267
}
@@ -252,5 +271,5 @@ func OutOfClusterAuth() (*kubernetes.Clientset, error) {
252271
panic(err.Error())
253272
}
254273

255-
return clientset, nil
274+
return clientset, kubeconf, nil
256275
}

0 commit comments

Comments
 (0)