@@ -22,35 +22,139 @@ package containerd
22
22
import (
23
23
"fmt"
24
24
"log/slog"
25
+ "os"
26
+ "os/exec"
27
+ "regexp"
25
28
"syscall"
26
29
27
30
"github.com/mitchellh/go-ps"
28
31
)
29
32
30
33
var psProcesses = ps .Processes
31
34
32
- type restarter struct {}
35
+ type defaultRestarter struct {}
33
36
34
- func NewRestarter () Restarter {
35
- return restarter {}
37
+ func NewDefaultRestarter () Restarter {
38
+ return defaultRestarter {}
36
39
}
37
40
38
- func (c restarter ) Restart () error {
39
- pid , err := getPid ()
41
+ func (c defaultRestarter ) Restart () error {
42
+ // If listing systemd units succeeds, prefer systemctl restart; otherwise kill pid
43
+ if _ , err := listSystemdUnits (); err == nil {
44
+ out , err := nsenterCmd ("systemctl" , "restart" , "containerd" ).CombinedOutput ()
45
+ slog .Debug (string (out ))
46
+ if err != nil {
47
+ return fmt .Errorf ("unable to restart containerd: %w" , err )
48
+ }
49
+ } else {
50
+ pid , err := getPid ("containerd" )
51
+ if err != nil {
52
+ return err
53
+ }
54
+ slog .Debug ("found containerd process" , "pid" , pid )
55
+
56
+ err = syscall .Kill (pid , syscall .SIGHUP )
57
+ if err != nil {
58
+ return fmt .Errorf ("failed to send SIGHUP to containerd: %w" , err )
59
+ }
60
+ }
61
+
62
+ return nil
63
+ }
64
+
65
+ type K0sRestarter struct {}
66
+
67
+ func (c K0sRestarter ) Restart () error {
68
+ // First, collect systemd units to determine which mode k0s is running in, eg
69
+ // k0sworker or k0scontroller
70
+ units , err := listSystemdUnits ()
71
+ if err != nil {
72
+ return fmt .Errorf ("unable to list systemd units: %w" , err )
73
+ }
74
+ service := regexp .MustCompile ("k0sworker|k0scontroller" ).FindString (string (units ))
75
+
76
+ out , err := nsenterCmd ("systemctl" , "restart" , service ).CombinedOutput ()
77
+ slog .Debug (string (out ))
78
+ if err != nil {
79
+ return fmt .Errorf ("unable to restart %s: %w" , service , err )
80
+ }
81
+
82
+ return nil
83
+ }
84
+
85
+ type K3sRestarter struct {}
86
+
87
+ func (c K3sRestarter ) Restart () error {
88
+ // This restarter will be used both for stock K3s distros, which use systemd as well as K3d, which does not.
89
+
90
+ // If listing systemd units succeeds, prefer systemctl restart; otherwise kill pid
91
+ if _ , err := listSystemdUnits (); err == nil {
92
+ out , err := nsenterCmd ("systemctl" , "restart" , "k3s" ).CombinedOutput ()
93
+ slog .Debug (string (out ))
94
+ if err != nil {
95
+ return fmt .Errorf ("unable to restart k3s: %w" , err )
96
+ }
97
+ } else {
98
+ // TODO: this approach still leads to the behavior mentioned in https://github.com/spinframework/runtime-class-manager/issues/140:
99
+ // The first pod's provisioner container exits with code 255, leading to pod status Unknown,
100
+ // followed by the subsequent pod's provisioner container no-op-ing and finishing with status Completed.
101
+ pid , err := getPid ("k3s" )
102
+ if err != nil {
103
+ return err
104
+ }
105
+ slog .Debug ("found k3s process" , "pid" , pid )
106
+
107
+ err = syscall .Kill (pid , syscall .SIGHUP )
108
+ if err != nil {
109
+ return fmt .Errorf ("failed to send SIGHUP to k3s: %w" , err )
110
+ }
111
+ }
112
+
113
+ return nil
114
+ }
115
+
116
+ type MicroK8sRestarter struct {}
117
+
118
+ func (c MicroK8sRestarter ) Restart () error {
119
+ out , err := nsenterCmd ("systemctl" , "restart" , "snap.microk8s.daemon-containerd" ).CombinedOutput ()
120
+ slog .Debug (string (out ))
40
121
if err != nil {
41
- return err
122
+ return fmt . Errorf ( "unable to restart snap.microk8s.daemon-containerd: %w" , err )
42
123
}
43
- slog .Debug ("found containerd process" , "pid" , pid )
44
124
45
- err = syscall .Kill (pid , syscall .SIGHUP )
125
+ return nil
126
+ }
127
+
128
+ type RKE2Restarter struct {}
129
+
130
+ func (c RKE2Restarter ) Restart () error {
131
+ // First, collect systemd units to determine which mode rke2 is running in, eg
132
+ // rke2-agent or rke2-server
133
+ units , err := listSystemdUnits ()
134
+ if err != nil {
135
+ return fmt .Errorf ("unable to list systemd units: %w" , err )
136
+ }
137
+ service := regexp .MustCompile ("rke2-agent|rke2-server" ).FindString (string (units ))
46
138
139
+ out , err := nsenterCmd ("systemctl" , "restart" , service ).CombinedOutput ()
140
+ slog .Debug (string (out ))
47
141
if err != nil {
48
- return fmt .Errorf ("failed to send SIGHUP to containerd : %w" , err )
142
+ return fmt .Errorf ("unable to restart %s : %w" , service , err )
49
143
}
144
+
50
145
return nil
51
146
}
52
147
53
- func getPid () (int , error ) {
148
+ func listSystemdUnits () ([]byte , error ) {
149
+ return nsenterCmd ("systemctl" , "list-units" , "--type" , "service" ).CombinedOutput ()
150
+ }
151
+
152
+ func nsenterCmd (cmd ... string ) * exec.Cmd {
153
+ return exec .Command ("nsenter" ,
154
+ append ([]string {fmt .Sprintf ("-m/%s/proc/1/ns/mnt" , os .Getenv ("HOST_ROOT" )), "--" }, cmd ... )... ) // #nosec G204
155
+ }
156
+
157
+ func getPid (executable string ) (int , error ) {
54
158
processes , err := psProcesses ()
55
159
if err != nil {
56
160
return 0 , fmt .Errorf ("could not get processes: %w" , err )
@@ -59,13 +163,13 @@ func getPid() (int, error) {
59
163
var containerdProcesses = []ps.Process {}
60
164
61
165
for _ , process := range processes {
62
- if process .Executable () == "containerd" {
166
+ if process .Executable () == executable {
63
167
containerdProcesses = append (containerdProcesses , process )
64
168
}
65
169
}
66
170
67
171
if len (containerdProcesses ) != 1 {
68
- return 0 , fmt .Errorf ("need exactly one containerd process, found: %d" , len (containerdProcesses ))
172
+ return 0 , fmt .Errorf ("need exactly one %s process, found: %d" , executable , len (containerdProcesses ))
69
173
}
70
174
71
175
return containerdProcesses [0 ].Pid (), nil
0 commit comments