go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/kubelet_flags.go (about)

     1  // copyright: 2019, Dominik Richter and Christoph Hartmann
     2  // author: Dominik Richter
     3  // author: Christoph Hartmann
     4  
     5  package resources
     6  
     7  import (
     8  	"regexp"
     9  	"strings"
    10  
    11  	"go.mondoo.com/cnquery/providers-sdk/v1/util/convert"
    12  )
    13  
    14  // mergeFlagsIntoConfig adds flags to the kubelet config
    15  // It does not take care of deprecated flags
    16  // The flags are not just kubelet specific, but can also be global flags
    17  // That also means, that some flags do not have a matching parameter in the kubelet config file and are added as is
    18  // The list of flags is taken from
    19  // /var/lib/minikube/binaries/v1.24.3/kubelet --help | grep -v DEPRECATED | grep -v -E "(vmodule|version|help|v level)"
    20  func mergeFlagsIntoConfig(kubeletConfig map[string]interface{}, flags map[string]interface{}) error {
    21  	cliOnlyFlags := []string{
    22  		"azure-container-registry-config",
    23  		"bootstrap-kubeconfig",
    24  		"cert-dir",
    25  		"config",
    26  		"container-runtime-endpoint",
    27  		"exit-on-lock-contention",
    28  		"hostname-override",
    29  		"housekeeping-interval",
    30  		"image-credential-provider-bin-dir",
    31  		"image-credential-provider-config",
    32  		"image-service-endpoint",
    33  		"kubeconfig",
    34  		"lock-file",
    35  		"log-flush-frequency",
    36  		"logging-format",
    37  		"node-ip",
    38  		"root-dir",
    39  		"runtime-cgroups",
    40  		"seccomp-default",
    41  	}
    42  	for _, key := range cliOnlyFlags {
    43  		if _, ok := flags[key]; ok {
    44  			kubeletConfig[key] = flags[key]
    45  		}
    46  	}
    47  
    48  	if _, ok := flags["node-labels"]; ok {
    49  		nodeLabels := map[string]string{}
    50  		for _, label := range strings.Split(flags["node-labels"].(string), ",") {
    51  			labelSplit := strings.Split(label, "=")
    52  			labelVal := ""
    53  			if len(labelSplit) > 1 {
    54  				labelVal = labelSplit[1]
    55  			}
    56  			nodeLabels[labelSplit[0]] = labelVal
    57  		}
    58  		data, err := convert.JsonToDict(nodeLabels)
    59  		if err != nil {
    60  			return err
    61  		}
    62  		kubeletConfig["node-labels"] = data
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  // mergeDeprecatedFlagsIntoConfig merges deprecated cli flags into the kubelet config
    69  // It only takes care of deprecated flags.
    70  // This is a seperate function in hope we can get rid of it in the future
    71  // The list of flags is taken from
    72  // https://github.com/kubernetes/kubernetes/blob/release-1.25/cmd/kubelet/app/options/options.go
    73  func mergeDeprecatedFlagsIntoConfig(kubeletConfig map[string]interface{}, flags map[string]interface{}) error {
    74  	evictionRegex := regexp.MustCompile(`^(.+)[<>=]+([\d]+[A-Za-z%]*)$`)
    75  
    76  	if _, ok := flags["enable-server"]; ok {
    77  		kubeletConfig["enableServer"] = flags["enable-server"]
    78  	}
    79  	if _, ok := flags["fail-swap-on"]; ok {
    80  		kubeletConfig["failSwapOn"] = flags["fail-swap-on"]
    81  	}
    82  	if _, ok := flags["pod-manifest-path"]; ok {
    83  		kubeletConfig["staticPodPath"] = flags["pod-manifest-path"]
    84  	}
    85  	if _, ok := flags["sync-frequency"]; ok {
    86  		kubeletConfig["syncFrequency"] = flags["sync-frequency"]
    87  	}
    88  	if _, ok := flags["file-check-frequency"]; ok {
    89  		kubeletConfig["fileCheckFrequency"] = flags["file-check-frequency"]
    90  	}
    91  	if _, ok := flags["http-check-frequency"]; ok {
    92  		kubeletConfig["httpCheckFrequency"] = flags["http-check-frequency"]
    93  	}
    94  	if _, ok := flags["manifest-url"]; ok {
    95  		kubeletConfig["staticPodURL"] = flags["manifest-url"]
    96  	}
    97  	if _, ok := flags["manifest-url-header"]; ok {
    98  		urlHeaders := map[string]string{}
    99  		for _, urlHeader := range strings.Split(flags["	"].(string), ",") {
   100  			urlHeaderSplit := strings.Split(urlHeader, ":")
   101  			urlHeaders[urlHeaderSplit[0]] = urlHeaderSplit[1]
   102  		}
   103  		data, err := convert.JsonToDict(urlHeaders)
   104  		if err != nil {
   105  			return err
   106  		}
   107  		kubeletConfig["staticPodURLHeader"] = data
   108  	}
   109  	if _, ok := flags["address"]; ok {
   110  		kubeletConfig["address"] = flags["address"]
   111  	}
   112  	if _, ok := flags["port"]; ok {
   113  		kubeletConfig["port"] = flags["port"]
   114  	}
   115  	if _, ok := flags["read-only-port"]; ok {
   116  		kubeletConfig["readOnlyPort"] = flags["read-only-port"]
   117  	}
   118  	if _, ok := flags["anonymous-auth"]; ok {
   119  		auth := map[string]interface{}{}
   120  		if _, ok := kubeletConfig["authentication"]; ok {
   121  			auth = kubeletConfig["authentication"].(map[string]interface{})
   122  		}
   123  		anon := map[string]interface{}{}
   124  		if _, ok := auth["anonymous"]; ok {
   125  			anon = auth["anonymous"].(map[string]interface{})
   126  		}
   127  		anon["enabled"] = flags["anonymous-auth"]
   128  	}
   129  	if _, ok := flags["authentication-token-webhook"]; ok {
   130  		auth := map[string]interface{}{}
   131  		if _, ok := kubeletConfig["authentication"]; ok {
   132  			auth = kubeletConfig["authentication"].(map[string]interface{})
   133  		}
   134  		webhook := map[string]interface{}{}
   135  		if _, ok := auth["webhook"]; ok {
   136  			webhook = auth["webhook"].(map[string]interface{})
   137  		}
   138  		webhook["enabled"] = flags["authentication-token-webhook"]
   139  	}
   140  	if _, ok := flags["authentication-token-webhook-cache-ttl"]; ok {
   141  		auth := map[string]interface{}{}
   142  		if _, ok := kubeletConfig["authentication"]; ok {
   143  			auth = kubeletConfig["authentication"].(map[string]interface{})
   144  		}
   145  		webhook := map[string]interface{}{}
   146  		if _, ok := auth["webhook"]; ok {
   147  			webhook = auth["webhook"].(map[string]interface{})
   148  		}
   149  		webhook["cacheTTL"] = flags["authentication-token-webhook-cache-ttl"].(string)
   150  		kubeletConfig["authentication"] = auth
   151  	}
   152  	if _, ok := flags["client-ca-file"]; ok {
   153  		authz := map[string]interface{}{}
   154  		if _, ok := kubeletConfig["authorization"]; ok {
   155  			authz = kubeletConfig["authorization"].(map[string]interface{})
   156  		}
   157  		x509 := map[string]interface{}{}
   158  		if _, ok := authz["x509"]; ok {
   159  			x509 = authz["x509"].(map[string]interface{})
   160  		}
   161  		x509["clientCAFile"] = flags["client-ca-file"]
   162  		kubeletConfig["authorization"] = authz
   163  	}
   164  	if _, ok := flags["authorization-mode"]; ok {
   165  		authz := map[string]interface{}{}
   166  		if _, ok := kubeletConfig["authorization"]; ok {
   167  			authz = kubeletConfig["authorization"].(map[string]interface{})
   168  		}
   169  		authz["mode"] = flags["authorization-mode"]
   170  		kubeletConfig["authorization"] = authz
   171  	}
   172  	if _, ok := flags["authorization-webhook-cache-authorized-ttl"]; ok {
   173  		authz := map[string]interface{}{}
   174  		if _, ok := kubeletConfig["authorization"]; ok {
   175  			authz = kubeletConfig["authorization"].(map[string]interface{})
   176  		}
   177  		webhook := map[string]interface{}{}
   178  		if _, ok := authz["webhook"]; ok {
   179  			webhook = authz["webhook"].(map[string]interface{})
   180  		}
   181  		webhook["cacheAuthorizedTTL"] = flags["authorization-webhook-cache-authorized-ttl"]
   182  		kubeletConfig["authorization"] = authz
   183  	}
   184  	if _, ok := flags["authorization-webhook-cache-unauthorized-ttl"]; ok {
   185  		authz := map[string]interface{}{}
   186  		if _, ok := kubeletConfig["authorization"]; ok {
   187  			authz = kubeletConfig["authorization"].(map[string]interface{})
   188  		}
   189  		webhook := map[string]interface{}{}
   190  		if _, ok := authz["webhook"]; ok {
   191  			webhook = authz["webhook"].(map[string]interface{})
   192  		}
   193  		webhook["cacheUnauthorizedTTL"] = flags["authorization-webhook-cache-unauthorized-ttl"]
   194  		kubeletConfig["authorization"] = authz
   195  	}
   196  	if _, ok := flags["tls-cert-file"]; ok {
   197  		kubeletConfig["tlsCertFile"] = flags["tls-cert-file"]
   198  	}
   199  	if _, ok := flags["tls-private-key-file"]; ok {
   200  		kubeletConfig["tlsPrivateKeyFile"] = flags["tls-private-key-file"]
   201  	}
   202  	if _, ok := flags["rotate-server-certificates"]; ok {
   203  		kubeletConfig["serverTLSBootstrap"] = flags["rotate-server-certificates"]
   204  	}
   205  	if _, ok := flags["tls-cipher-suites"]; ok {
   206  		ciphers := strings.Split(flags["tls-cipher-suites"].(string), ",")
   207  		data, err := convert.JsonToDictSlice(ciphers)
   208  		if err != nil {
   209  			return err
   210  		}
   211  		kubeletConfig["tlsCipherSuites"] = data
   212  	}
   213  	if _, ok := flags["tls-min-version"]; ok {
   214  		kubeletConfig["tlsMinVersion"] = flags["tls-min-version"]
   215  	}
   216  	if _, ok := flags["rotate-certificates"]; ok {
   217  		kubeletConfig["rotateCertificates"] = flags["rotate-certificates"]
   218  	}
   219  	if _, ok := flags["registry-qps"]; ok {
   220  		kubeletConfig["registryPullQPS"] = flags["registry-qps"]
   221  	}
   222  	if _, ok := flags["registry-burst"]; ok {
   223  		kubeletConfig["registryBurst"] = flags["registry-burst"]
   224  	}
   225  	if _, ok := flags["event-qps"]; ok {
   226  		kubeletConfig["eventRecordQPS"] = flags["event-qps"]
   227  	}
   228  	if _, ok := flags["event-burst"]; ok {
   229  		kubeletConfig["eventBurst"] = flags["event-burst"]
   230  	}
   231  	if _, ok := flags["enable-debugging-handlers"]; ok {
   232  		kubeletConfig["enableDebuggingHandlers"] = flags["enable-debugging-handlers"]
   233  	}
   234  	if _, ok := flags["contention-profiling"]; ok {
   235  		kubeletConfig["enableContentionProfiling"] = flags["contention-profiling"]
   236  	}
   237  	if _, ok := flags["healthz-port"]; ok {
   238  		kubeletConfig["healthzPort"] = flags["healthz-port"]
   239  	}
   240  	if _, ok := flags["healthz-bind-address"]; ok {
   241  		kubeletConfig["healthzBindAddress"] = flags["healthz-bind-address"]
   242  	}
   243  	if _, ok := flags["oom-score-adj"]; ok {
   244  		kubeletConfig["oomScoreAdj"] = flags["oom-score-adj"]
   245  	}
   246  	if _, ok := flags["cluster-domain"]; ok {
   247  		kubeletConfig["clusterDomain"] = flags["cluster-domain"]
   248  	}
   249  	if _, ok := flags["volume-plugin-dir"]; ok {
   250  		kubeletConfig["volumePluginDir"] = flags["volume-plugin-dir"]
   251  	}
   252  	if _, ok := flags["cluster-dns"]; ok {
   253  		kubeletConfig["clusterDNS"] = flags["cluster-dns"]
   254  	}
   255  	if _, ok := flags["streaming-connection-idle-timeout"]; ok {
   256  		kubeletConfig["streamingConnectionIdleTimeout"] = flags["streaming-connection-idle-timeout"]
   257  	}
   258  	if _, ok := flags["node-status-update-frequency"]; ok {
   259  		kubeletConfig["nodeStatusUpdateFrequency"] = flags["node-status-update-frequency"]
   260  	}
   261  	if _, ok := flags["minimum-image-ttl-duration"]; ok {
   262  		kubeletConfig["imageMinimumGCAge"] = flags["minimum-image-ttl-duration"]
   263  	}
   264  	if _, ok := flags["image-gc-high-threshold"]; ok {
   265  		kubeletConfig["imageGCHighThresholdPercent"] = flags["image-gc-high-threshold"]
   266  	}
   267  	if _, ok := flags["image-gc-low-threshold"]; ok {
   268  		kubeletConfig["imageGCLowThresholdPercent"] = flags["image-gc-low-threshold"]
   269  	}
   270  	if _, ok := flags["volume-stats-agg-period"]; ok {
   271  		kubeletConfig["volumeStatsAggPeriod"] = flags["volume-stats-agg-period"]
   272  	}
   273  	if _, ok := flags["feature-gates"]; ok {
   274  		featureFlags := map[string]string{}
   275  		for _, feature := range strings.Split(flags["feature-gates"].(string), ",") {
   276  			featureSplit := strings.Split(feature, "=")
   277  			featureFlags[featureSplit[0]] = featureSplit[1]
   278  		}
   279  		data, err := convert.JsonToDict(featureFlags)
   280  		if err != nil {
   281  			return err
   282  		}
   283  		kubeletConfig["featureGates"] = data
   284  	}
   285  	if _, ok := flags["kubelet-cgroups"]; ok {
   286  		kubeletConfig["kubeletCgroups"] = flags["kubelet-cgroups"]
   287  	}
   288  	if _, ok := flags["system-cgroups"]; ok {
   289  		kubeletConfig["systemCgroups"] = flags["system-cgroups"]
   290  	}
   291  	if _, ok := flags["provider-id"]; ok {
   292  		kubeletConfig["providerID"] = flags["provider-id"]
   293  	}
   294  	if _, ok := flags["cgroups-per-qos"]; ok {
   295  		kubeletConfig["cgroupsPerQOS"] = flags["cgroups-per-qos"]
   296  	}
   297  	if _, ok := flags["cgroup-driver"]; ok {
   298  		kubeletConfig["cgroupDriver"] = flags["cgroup-driver"]
   299  	}
   300  	if _, ok := flags["cgroup-root"]; ok {
   301  		kubeletConfig["cgroupRoot"] = flags["cgroup-root"]
   302  	}
   303  	if _, ok := flags["cpu-manager-policy"]; ok {
   304  		kubeletConfig["cpuManagerPolicy"] = flags["cpu-manager-policy"]
   305  	}
   306  	if _, ok := flags["cpu-manager-policy-options"]; ok {
   307  		cpuPolicies := map[string]string{}
   308  		for _, cpuPolicy := range strings.Split(flags["cpu-manager-policy-options"].(string), ",") {
   309  			cpuPolicySplit := strings.Split(cpuPolicy, "=")
   310  			cpuPolicies[cpuPolicySplit[0]] = cpuPolicySplit[1]
   311  		}
   312  		data, err := convert.JsonToDict(cpuPolicies)
   313  		if err != nil {
   314  			return err
   315  		}
   316  		kubeletConfig["cpuManagerPolicyOptions"] = data
   317  	}
   318  	if _, ok := flags["cpu-manager-reconcile-period"]; ok {
   319  		kubeletConfig["cpuManagerReconcilePeriod"] = flags["cpu-manager-reconcile-period"]
   320  	}
   321  	if _, ok := flags["qos-reserved"]; ok {
   322  		qosReserved := map[string]string{}
   323  		for _, qosReserve := range strings.Split(flags["qos-reserved"].(string), ",") {
   324  			qosReserveSplit := strings.Split(qosReserve, "=")
   325  			qosReserved[qosReserveSplit[0]] = qosReserveSplit[1]
   326  		}
   327  		data, err := convert.JsonToDict(qosReserved)
   328  		if err != nil {
   329  			return err
   330  		}
   331  		kubeletConfig["qosReserved"] = data
   332  	}
   333  	if _, ok := flags["topology-manager-policy"]; ok {
   334  		kubeletConfig["topologyManagerPolicy"] = flags["topology-manager-policy"]
   335  	}
   336  	if _, ok := flags["runtime-request-timeout"]; ok {
   337  		kubeletConfig["runtimeRequestTimeout"] = flags["runtime-request-timeout"]
   338  	}
   339  	if _, ok := flags["hairpin-mode"]; ok {
   340  		kubeletConfig["hairpinMode"] = flags["hairpin-mode"]
   341  	}
   342  	if _, ok := flags["max-pods"]; ok {
   343  		kubeletConfig["maxPods"] = flags["max-pods"]
   344  	}
   345  	if _, ok := flags["pod-cidr"]; ok {
   346  		kubeletConfig["podCIDR"] = flags["pod-cidr"]
   347  	}
   348  	if _, ok := flags["pod-max-pids"]; ok {
   349  		kubeletConfig["podPidsLimit"] = flags["pod-max-pids"]
   350  	}
   351  	if _, ok := flags["resolv-conf"]; ok {
   352  		kubeletConfig["resolverConfig"] = flags["resolv-conf"]
   353  	}
   354  	if _, ok := flags["runonce"]; ok {
   355  		kubeletConfig["runOnce"] = flags["runonce"]
   356  	}
   357  	if _, ok := flags["cpu-cfs-quota"]; ok {
   358  		kubeletConfig["cpuCFSQuota"] = flags["cpu-cfs-quota"]
   359  	}
   360  	if _, ok := flags["cpu-cfs-quota-period"]; ok {
   361  		kubeletConfig["cpuCFSQuotaPeriod"] = flags["cpu-cfs-quota-period"]
   362  	}
   363  	if _, ok := flags["enable-controller-attach-detach"]; ok {
   364  		kubeletConfig["enableControllerAttachDetach"] = flags["enable-controller-attach-detach"]
   365  	}
   366  	if _, ok := flags["make-iptables-util-chains"]; ok {
   367  		kubeletConfig["makeIPTablesUtilChains"] = flags["make-iptables-util-chains"]
   368  	}
   369  	if _, ok := flags["iptables-masquerade-bit"]; ok {
   370  		kubeletConfig["iptablesMasqueradeBit"] = flags["iptables-masquerade-bit"]
   371  	}
   372  	if _, ok := flags["iptables-drop-bit"]; ok {
   373  		kubeletConfig["iptablesDropBit"] = flags["iptables-drop-bit"]
   374  	}
   375  	if _, ok := flags["container-log-max-size"]; ok {
   376  		kubeletConfig["containerLogMaxSize"] = flags["container-log-max-size"]
   377  	}
   378  	if _, ok := flags["container-log-max-files"]; ok {
   379  		kubeletConfig["containerLogMaxFiles"] = flags["container-log-max-files"]
   380  	}
   381  	if _, ok := flags["allowed-unsafe-sysctls"]; ok {
   382  		kubeletConfig["allowedUnsafeSysctls"] = flags["allowed-unsafe-sysctls"]
   383  	}
   384  	if _, ok := flags["node-status-max-images"]; ok {
   385  		kubeletConfig["nodeStatusMaxImages"] = flags["node-status-max-images"]
   386  	}
   387  	if _, ok := flags["kernel-memcg-notification"]; ok {
   388  		kubeletConfig["kernelMemcgNotification"] = flags["kernel-memcg-notification"]
   389  	}
   390  	if _, ok := flags["local-storage-capacity-isolation"]; ok {
   391  		kubeletConfig["localStorageCapacityIsolation"] = flags["local-storage-capacity-isolation"]
   392  	}
   393  	if _, ok := flags["max-open-files"]; ok {
   394  		kubeletConfig["maxOpenFiles"] = flags["max-open-files"]
   395  	}
   396  	if _, ok := flags["kube-api-content-type"]; ok {
   397  		kubeletConfig["contentType"] = flags["kube-api-content-type"]
   398  	}
   399  	if _, ok := flags["kube-api-qps"]; ok {
   400  		kubeletConfig["kubeAPIQPS"] = flags["kube-api-qps"]
   401  	}
   402  	if _, ok := flags["kube-api-burst"]; ok {
   403  		kubeletConfig["kubeAPIBurst"] = flags["kube-api-burst"]
   404  	}
   405  	if _, ok := flags["serialize-image-pulls"]; ok {
   406  		kubeletConfig["serializeImagePulls"] = flags["serialize-image-pulls"]
   407  	}
   408  	if _, ok := flags["eviction-hard"]; ok {
   409  		evictions := map[string]string{}
   410  		for _, eviction := range strings.Split(flags["eviction-hard"].(string), ",") {
   411  			m := evictionRegex.FindStringSubmatch(eviction)
   412  			if len(m) == 0 {
   413  				continue
   414  			}
   415  			evictions[m[1]] = m[2]
   416  		}
   417  		data, err := convert.JsonToDict(evictions)
   418  		if err != nil {
   419  			return err
   420  		}
   421  		kubeletConfig["evictionHard"] = data
   422  	}
   423  	if _, ok := flags["eviction-soft"]; ok {
   424  		evictions := map[string]string{}
   425  		for _, eviction := range strings.Split(flags["eviction-soft"].(string), ",") {
   426  			m := evictionRegex.FindStringSubmatch(eviction)
   427  			if len(m) == 0 {
   428  				continue
   429  			}
   430  			evictions[m[1]] = m[2]
   431  		}
   432  		data, err := convert.JsonToDict(evictions)
   433  		if err != nil {
   434  			return err
   435  		}
   436  		kubeletConfig["evictionSoft"] = data
   437  	}
   438  	if _, ok := flags["eviction-soft-grace-period"]; ok {
   439  		softPeriods := map[string]string{}
   440  		for _, softPeriod := range strings.Split(flags["eviction-soft-grace-period"].(string), ",") {
   441  			softPeriodSplit := strings.Split(softPeriod, "=")
   442  			softPeriods[softPeriodSplit[0]] = softPeriodSplit[1]
   443  		}
   444  		data, err := convert.JsonToDict(softPeriods)
   445  		if err != nil {
   446  			return err
   447  		}
   448  		kubeletConfig["evictionSoftGracePeriod"] = data
   449  	}
   450  	if _, ok := flags["eviction-pressure-transition-period"]; ok {
   451  		kubeletConfig["evictionPressureTransitionPeriod"] = flags["eviction-pressure-transition-period"]
   452  	}
   453  	if _, ok := flags["eviction-max-pod-grace-period"]; ok {
   454  		kubeletConfig["evictionMaxPodGracePeriod"] = flags["eviction-max-pod-grace-period"]
   455  	}
   456  	if _, ok := flags["eviction-minimum-reclaim"]; ok {
   457  		minReclaims := map[string]string{}
   458  		for _, minReclaim := range strings.Split(flags["eviction-minimum-reclaim"].(string), ",") {
   459  			minReclaimSplit := strings.Split(minReclaim, "=")
   460  			minReclaims[minReclaimSplit[0]] = minReclaimSplit[1]
   461  		}
   462  		data, err := convert.JsonToDict(minReclaims)
   463  		if err != nil {
   464  			return err
   465  		}
   466  		kubeletConfig["evictionMinimumReclaim"] = data
   467  	}
   468  	if _, ok := flags["pods-per-core"]; ok {
   469  		kubeletConfig["podsPerCore"] = flags["pods-per-core"]
   470  	}
   471  	if _, ok := flags["protect-kernel-defaults"]; ok {
   472  		kubeletConfig["protectKernelDefaults"] = flags["protect-kernel-defaults"]
   473  	}
   474  	if _, ok := flags["reserved-cpus"]; ok {
   475  		kubeletConfig["reservedSystemCPUs"] = flags["reserved-cpus"]
   476  	}
   477  	if _, ok := flags["topology-manager-scope"]; ok {
   478  		kubeletConfig["topologyManagerScope"] = flags["topology-manager-scope"]
   479  	}
   480  	if _, ok := flags["system-reserved"]; ok {
   481  		systemReserved := map[string]string{}
   482  		for _, systemReserve := range strings.Split(flags["system-reserved"].(string), ",") {
   483  			systemReserveSplit := strings.Split(systemReserve, "=")
   484  			systemReserved[systemReserveSplit[0]] = systemReserveSplit[1]
   485  		}
   486  		data, err := convert.JsonToDict(systemReserved)
   487  		if err != nil {
   488  			return err
   489  		}
   490  		kubeletConfig["systemReserved"] = data
   491  	}
   492  	if _, ok := flags["kube-reserved"]; ok {
   493  		kubeReserved := map[string]string{}
   494  		for _, kubeReserve := range strings.Split(flags["kube-reserved"].(string), ",") {
   495  			kubeReserveSplit := strings.Split(kubeReserve, "=")
   496  			kubeReserved[kubeReserveSplit[0]] = kubeReserveSplit[1]
   497  		}
   498  		data, err := convert.JsonToDict(kubeReserved)
   499  		if err != nil {
   500  			return err
   501  		}
   502  		kubeletConfig["kubeReserved"] = data
   503  	}
   504  	if _, ok := flags["enforce-node-allocatable"]; ok {
   505  		kubeletConfig["enforceNodeAllocatable"] = flags["enforce-node-allocatable"]
   506  	}
   507  	if _, ok := flags["system-reserved-cgroup"]; ok {
   508  		kubeletConfig["systemReservedCgroup"] = flags["system-reserved-cgroup"]
   509  	}
   510  	if _, ok := flags["kube-reserved-cgroup"]; ok {
   511  		kubeletConfig["kubeReservedCgroup"] = flags["kube-reserved-cgroup"]
   512  	}
   513  	if _, ok := flags["memory-manager-policy"]; ok {
   514  		kubeletConfig["memoryManagerPolicy"] = flags["memory-manager-policy"]
   515  	}
   516  	if _, ok := flags["reserved-memory"]; ok {
   517  		reservations := strings.Split(flags["reserved-memory"].(string), ",")
   518  		data, err := convert.JsonToDictSlice(reservations)
   519  		if err != nil {
   520  			return err
   521  		}
   522  		kubeletConfig["reservedMemory"] = data
   523  	}
   524  	if _, ok := flags["register-node"]; ok {
   525  		kubeletConfig["registerNode"] = flags["register-node"]
   526  	}
   527  	if _, ok := flags["register-with-taints"]; ok {
   528  		taints := strings.Split(flags["register-with-taints"].(string), ",")
   529  		data, err := convert.JsonToDictSlice(taints)
   530  		if err != nil {
   531  			return err
   532  		}
   533  		kubeletConfig["registerWithTaints"] = data
   534  	}
   535  
   536  	// Looks like these flags do not have a corresponding config option in the file:
   537  	deprecatedCliOnlyFlags := []string{
   538  		"minimum-container-ttl-duration",
   539  		"maximum-dead-containers-per-container",
   540  		"maximum-dead-containers",
   541  		"master-service-namespace",
   542  		"register-schedulable",
   543  		"keep-terminated-pod-volumes",
   544  		"experimental-mounter-path",
   545  		"cloud-provider",
   546  		"cloud-config",
   547  		"experimental-allocatable-ignore-eviction",
   548  	}
   549  	for _, key := range deprecatedCliOnlyFlags {
   550  		if _, ok := flags[key]; ok {
   551  			kubeletConfig[key] = flags[key]
   552  		}
   553  	}
   554  
   555  	return nil
   556  }