@@ -30,6 +30,10 @@ var criDefaultConfigPath = "/etc/crictl.yaml"
30
30
31
31
// main entrypoint for the k3s multicall binary
32
32
func main () {
33
+ if findDebug (os .Args ) {
34
+ logrus .SetLevel (logrus .DebugLevel )
35
+ }
36
+
33
37
dataDir := findDataDir (os .Args )
34
38
35
39
// Handle direct invocation via symlink alias (multicall binary behavior)
@@ -87,6 +91,24 @@ func main() {
87
91
}
88
92
}
89
93
94
+ // findDebug reads debug settings from the environment, CLI args, and config file.
95
+ func findDebug (args []string ) bool {
96
+ debug , _ := strconv .ParseBool (os .Getenv (version .ProgramUpper + "_DEBUG" ))
97
+ if debug {
98
+ return debug
99
+ }
100
+ fs := pflag .NewFlagSet ("debug-set" , pflag .ContinueOnError )
101
+ fs .ParseErrorsWhitelist .UnknownFlags = true
102
+ fs .SetOutput (io .Discard )
103
+ fs .BoolVarP (& debug , "debug" , "" , false , "(logging) Turn on debug logs" )
104
+ fs .Parse (args )
105
+ if debug {
106
+ return debug
107
+ }
108
+ debug , _ = strconv .ParseBool (configfilearg .MustFindString (args , "debug" ))
109
+ return debug
110
+ }
111
+
90
112
// findDataDir reads data-dir settings from the environment, CLI args, and config file.
91
113
// If not found, the default will be used, which varies depending on whether
92
114
// k3s is being run as root or not.
@@ -280,31 +302,45 @@ func extract(dataDir string) (string, error) {
280
302
return "" , err
281
303
}
282
304
283
- // Rename the new directory into place, before updating symlinks
284
- if err := os .Rename (tempDest , dir ); err != nil {
285
- return "" , err
286
- }
287
-
288
305
// Create a stable CNI bin dir and place it first in the path so that users have a
289
306
// consistent location to drop their own CNI plugin binaries.
290
307
cniPath := filepath .Join (dataDir , "data" , "cni" )
291
308
cniBin := filepath .Join (dir , "bin" , "cni" )
292
309
if err := os .MkdirAll (cniPath , 0755 ); err != nil {
293
310
return "" , err
294
311
}
312
+ // Create symlink that points at the cni multicall binary itself
313
+ logrus .Debugf ("Creating symlink %s -> %s" , filepath .Join (cniPath , "cni" ), cniBin )
314
+ os .Remove (filepath .Join (cniPath , "cni" ))
295
315
if err := os .Symlink (cniBin , filepath .Join (cniPath , "cni" )); err != nil {
296
316
return "" , err
297
317
}
298
318
299
319
// Find symlinks that point to the cni multicall binary, and clone them in the stable CNI bin dir.
300
- ents , err := os .ReadDir (filepath .Join (dir , "bin" ))
320
+ // Non-symlink plugins in the stable CNI bin dir will not be overwritten, to allow users to replace our
321
+ // CNI plugins with their own versions if they want. Note that the cni multicall binary itself is always
322
+ // symlinked into the stable bin dir and should not be replaced.
323
+ ents , err := os .ReadDir (filepath .Join (tempDest , "bin" ))
301
324
if err != nil {
302
325
return "" , err
303
326
}
304
327
for _ , ent := range ents {
305
328
if info , err := ent .Info (); err == nil && info .Mode ()& fs .ModeSymlink != 0 {
306
- if target , err := os .Readlink (filepath .Join (dir , "bin" , ent .Name ())); err == nil && target == "cni" {
307
- if err := os .Symlink (cniBin , filepath .Join (cniPath , ent .Name ())); err != nil {
329
+ if target , err := os .Readlink (filepath .Join (tempDest , "bin" , ent .Name ())); err == nil && target == "cni" {
330
+ src := filepath .Join (cniPath , ent .Name ())
331
+ // Check if plugin already exists in stable CNI bin dir
332
+ if info , err := os .Lstat (src ); err == nil {
333
+ if info .Mode ()& fs .ModeSymlink != 0 {
334
+ // Exists and is a symlink, remove it so we can create a new symlink for the new bin.
335
+ os .Remove (src )
336
+ } else {
337
+ // Not a symlink, leave it alone
338
+ logrus .Debugf ("Not replacing non-symlink CNI plugin %s with mode %O" , src , info .Mode ())
339
+ continue
340
+ }
341
+ }
342
+ logrus .Debugf ("Creating symlink %s -> %s" , src , cniBin )
343
+ if err := os .Symlink (cniBin , src ); err != nil {
308
344
return "" , err
309
345
}
310
346
}
@@ -324,6 +360,12 @@ func extract(dataDir string) (string, error) {
324
360
return "" , err
325
361
}
326
362
363
+ // Rename the new directory into place after updating symlinks, so that the k3s binary check at the start
364
+ // of this function only succeeds if everything else has been completed successfully.
365
+ if err := os .Rename (tempDest , dir ); err != nil {
366
+ return "" , err
367
+ }
368
+
327
369
return dir , nil
328
370
}
329
371
0 commit comments