-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
178 lines (158 loc) · 5.15 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
175
176
177
178
package main
import (
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func main() {
namespaceName := getNamespace()
podName := getPodName()
linkerdContainer := getLinkerdProxyName()
proxyTerminator := getProxyTerminatorName()
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// get pod info
podInfo, err := getPodInfo(clientset, podName, namespaceName)
if err != nil {
panic(err.Error())
} else {
fmt.Printf("Found %s pod in %s namespace\n", podName, namespaceName)
}
// check if there is container linkerd-proxy in the podInfo containers list.
linkerdProxy := false
for _, container := range podInfo.Spec.Containers {
if container.Name == linkerdContainer {
fmt.Printf("Found %s container\n", linkerdContainer)
linkerdProxy = true
break
}
}
// create a new variable watchContainers array list and store the list of containers except linkerd-proxy and proxy-terminator
var watchContainers []string
watchContainers = []string{}
for _, container := range podInfo.Spec.Containers {
if container.Name != linkerdContainer && container.Name != proxyTerminator {
watchContainers = append(watchContainers, container.Name)
}
}
fmt.Printf("Watching containers: %v\n", watchContainers)
// watch containers every 5 seconds if ther are completed
runningWatchContainers := len(watchContainers)
for runningWatchContainers > 0 {
fmt.Printf("Running watch containers count: %v\n", runningWatchContainers)
time.Sleep(10 * time.Second)
podInfo, err = getPodInfo(clientset, podName, namespaceName)
if err != nil {
panic(err.Error())
}
for _, watchContainer := range watchContainers {
for _, container := range podInfo.Status.ContainerStatuses {
if container.Name == watchContainer {
fmt.Printf("Container: %s, Status: %s\n", container.Name, container.State.String())
if container.State.Terminated != nil {
fmt.Printf("Container %s has terminated as it is %s\n", watchContainer, container.State.Terminated.Reason)
runningWatchContainers--
} else {
fmt.Printf("Container %s is still running. Terminated: %s\n", watchContainer, container.State.Terminated)
}
}
}
}
}
if !linkerdProxy {
fmt.Printf("No %s container. Goodbye..\n", linkerdContainer)
} else {
fmt.Println("All watching containers are terminated. Terminating linkerd proxy container...")
err = terminateLinkerdProxy()
if err != nil {
panic(err.Error())
}
}
}
// getPodName function which get the value from env POD_NAME otherwise get the value from env HOSTNAME
func getPodName() string {
podName := os.Getenv("POD_NAME")
if podName == "" {
podName = os.Getenv("HOSTNAME")
}
return podName
}
// getLinkerdProxyName function which get the value from env LINKERD_PROXY_NAME otherwise set the value to linkerd-proxy
func getLinkerdProxyName() string {
linkerdProxyName := os.Getenv("LINKERD_PROXY_NAME")
if linkerdProxyName == "" {
linkerdProxyName = "linkerd-proxy"
}
return linkerdProxyName
}
// getProxyTerminatorName function which get the value from env PROXY_TERMINATOR_NAME otherwise set the value to linkerd-proxy-terminator
func getProxyTerminatorName() string {
proxyTerminatorName := os.Getenv("PROXY_TERMINATOR_NAME")
if proxyTerminatorName == "" {
proxyTerminatorName = "linkerd-proxy-terminator"
}
return proxyTerminatorName
}
// getNamespace function which reads the file /var/run/secrets/kubernetes.io/serviceaccount and return the namespace name as string
func getNamespace() string {
// create the file
file, err := os.Open("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
log.Fatal(err)
}
// read the file
data, err := io.ReadAll(file)
if err != nil {
log.Fatal(err)
}
// return the namespace name
return string(data)
}
// getPodInfo function which returns the pod info from clientset by passing podName and namespaceName
func getPodInfo(clientset *kubernetes.Clientset, podName string, namespaceName string) (*v1.Pod, error) {
pod, err := clientset.CoreV1().Pods(namespaceName).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
fmt.Printf("Pod %s not found in %s namespace\n", podName, namespaceName)
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
fmt.Printf("Error getting pod %v\n", statusError.ErrStatus.Message)
} else {
return nil, err
}
}
return pod, err
}
// terminateLinkerdProxy function by calling POST request to http://localhost:4191/shutdown
func terminateLinkerdProxy() error {
url := "http://localhost:4191/shutdown"
client := &http.Client{}
req, err := http.NewRequest("POST", url, nil)
if err != nil {
fmt.Println("Error creating http request:", err)
return err
}
_, err = client.Do(req)
if err != nil {
fmt.Println("Error terminating request:", err)
return err
}
fmt.Println("Terminated linkerd proxy!")
return nil
}