@@ -42,6 +42,7 @@ import (
42
42
"google.golang.org/grpc/codes"
43
43
"google.golang.org/grpc/status"
44
44
jsonpatch "gopkg.in/evanphx/json-patch.v4"
45
+
45
46
"k8s.io/klog/v2"
46
47
"k8s.io/mount-utils"
47
48
@@ -51,9 +52,11 @@ import (
51
52
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
52
53
oteltrace "go.opentelemetry.io/otel/trace"
53
54
noopoteltrace "go.opentelemetry.io/otel/trace/noop"
55
+
54
56
v1 "k8s.io/api/core/v1"
55
57
"k8s.io/apimachinery/pkg/api/resource"
56
58
"k8s.io/apimachinery/pkg/runtime"
59
+ "k8s.io/apimachinery/pkg/runtime/schema"
57
60
"k8s.io/apimachinery/pkg/types"
58
61
utilnet "k8s.io/apimachinery/pkg/util/net"
59
62
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -94,6 +97,7 @@ import (
94
97
"k8s.io/kubernetes/pkg/kubelet"
95
98
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
96
99
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/config/scheme"
100
+ kubeletconfigv1beta1conversion "k8s.io/kubernetes/pkg/kubelet/apis/config/v1beta1"
97
101
kubeletconfigvalidation "k8s.io/kubernetes/pkg/kubelet/apis/config/validation"
98
102
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
99
103
kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate"
@@ -316,7 +320,15 @@ is checked every 20 seconds (also configurable with a flag).`,
316
320
// potentially overriding the previous values.
317
321
func mergeKubeletConfigurations (kubeletConfig * kubeletconfiginternal.KubeletConfiguration , kubeletDropInConfigDir string ) error {
318
322
const dropinFileExtension = ".conf"
319
- baseKubeletConfigJSON , err := json .Marshal (kubeletConfig )
323
+
324
+ // TODO: move the "internal --> versioned --> merge --> default --> internal" operation inside the loop,
325
+ // and use the version of each drop-in file as the versioned target once config files can be in versions other than just v1beta1
326
+ versionedConfig := & kubeletconfigv1beta1.KubeletConfiguration {}
327
+ if err := kubeletconfigv1beta1conversion .Convert_config_KubeletConfiguration_To_v1beta1_KubeletConfiguration (kubeletConfig , versionedConfig , nil ); err != nil {
328
+ return err
329
+ }
330
+
331
+ baseKubeletConfigJSON , err := json .Marshal (versionedConfig )
320
332
if err != nil {
321
333
return fmt .Errorf ("failed to marshal base config: %w" , err )
322
334
}
@@ -326,10 +338,17 @@ func mergeKubeletConfigurations(kubeletConfig *kubeletconfiginternal.KubeletConf
326
338
return err
327
339
}
328
340
if ! info .IsDir () && filepath .Ext (info .Name ()) == dropinFileExtension {
329
- dropinConfigJSON , err := loadDropinConfigFileIntoJSON (path )
341
+ dropinConfigJSON , gvk , err := loadDropinConfigFileIntoJSON (path )
330
342
if err != nil {
331
343
return fmt .Errorf ("failed to load kubelet dropin file, path: %s, error: %w" , path , err )
332
344
}
345
+ if gvk == nil || gvk .Empty () {
346
+ return fmt .Errorf ("failed to load kubelet dropin file, path: %s, no apiVersion/kind" , path )
347
+ }
348
+ // TODO: expand this once more than a single kubelet config version exists
349
+ if * gvk != kubeletconfigv1beta1 .SchemeGroupVersion .WithKind ("KubeletConfiguration" ) {
350
+ return fmt .Errorf ("failed to load kubelet dropin file, path: %s, unknown apiVersion/kind: %v" , path , gvk .String ())
351
+ }
333
352
mergedConfigJSON , err := jsonpatch .MergePatch (baseKubeletConfigJSON , dropinConfigJSON )
334
353
if err != nil {
335
354
return fmt .Errorf ("failed to merge drop-in and current config: %w" , err )
@@ -341,9 +360,18 @@ func mergeKubeletConfigurations(kubeletConfig *kubeletconfiginternal.KubeletConf
341
360
return fmt .Errorf ("failed to walk through kubelet dropin directory %q: %w" , kubeletDropInConfigDir , err )
342
361
}
343
362
344
- if err := json .Unmarshal (baseKubeletConfigJSON , kubeletConfig ); err != nil {
363
+ // reset versioned config and decode
364
+ versionedConfig = & kubeletconfigv1beta1.KubeletConfiguration {}
365
+ if err := json .Unmarshal (baseKubeletConfigJSON , versionedConfig ); err != nil {
345
366
return fmt .Errorf ("failed to unmarshal merged JSON into kubelet configuration: %w" , err )
346
367
}
368
+ // apply defaulting after decoding
369
+ kubeletconfigv1beta1conversion .SetDefaults_KubeletConfiguration (versionedConfig )
370
+ // convert back to internal config
371
+ if err := kubeletconfigv1beta1conversion .Convert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration (versionedConfig , kubeletConfig , nil ); err != nil {
372
+ return fmt .Errorf ("failed to convert merged config to internal kubelet configuration: %w" , err )
373
+ }
374
+
347
375
return nil
348
376
}
349
377
@@ -423,16 +451,16 @@ func loadConfigFile(name string) (*kubeletconfiginternal.KubeletConfiguration, e
423
451
return kc , err
424
452
}
425
453
426
- func loadDropinConfigFileIntoJSON (name string ) ([]byte , error ) {
454
+ func loadDropinConfigFileIntoJSON (name string ) ([]byte , * schema. GroupVersionKind , error ) {
427
455
const errFmt = "failed to load drop-in kubelet config file %s, error %v"
428
456
// compute absolute path based on current working dir
429
457
kubeletConfigFile , err := filepath .Abs (name )
430
458
if err != nil {
431
- return nil , fmt .Errorf (errFmt , name , err )
459
+ return nil , nil , fmt .Errorf (errFmt , name , err )
432
460
}
433
461
loader , err := configfiles .NewFsLoader (& utilfs.DefaultFs {}, kubeletConfigFile )
434
462
if err != nil {
435
- return nil , fmt .Errorf (errFmt , name , err )
463
+ return nil , nil , fmt .Errorf (errFmt , name , err )
436
464
}
437
465
return loader .LoadIntoJSON ()
438
466
}
0 commit comments