kubeadm: update the rest of the code base for structured ExtraArgs

In all places map[string]string compounds were used directly
for extra args. Modify said locations to use []Arg
and the new utilities Get/SetArgValue(), ArgumentsTo/FromCommand().
This commit is contained in:
Lubomir I. Ivanov 2023-07-05 18:33:05 +03:00
parent a505c7160e
commit f3da0d4ed3
10 changed files with 202 additions and 179 deletions

View File

@ -26,6 +26,7 @@ import (
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2" "k8s.io/klog/v2"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/options" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/options"
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow" "k8s.io/kubernetes/cmd/kubeadm/app/cmd/phases/workflow"
cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util" cmdutil "k8s.io/kubernetes/cmd/kubeadm/app/cmd/util"
@ -78,8 +79,8 @@ func runKubeletFinalizeCertRotation(c workflow.RunData) error {
// If yes, use that path, else use the kubeadm provided value. // If yes, use that path, else use the kubeadm provided value.
cfg := data.Cfg() cfg := data.Cfg()
pkiPath := filepath.Join(data.KubeletDir(), "pki") pkiPath := filepath.Join(data.KubeletDir(), "pki")
val, ok := cfg.NodeRegistration.KubeletExtraArgs["cert-dir"] val, idx := kubeadmapi.GetArgValue(cfg.NodeRegistration.KubeletExtraArgs, "cert-dir", -1)
if ok { if idx > -1 {
pkiPath = val pkiPath = val
} }

View File

@ -162,46 +162,47 @@ func CreateStaticPodFiles(manifestDir, patchesDir string, cfg *kubeadmapi.Cluste
// getAPIServerCommand builds the right API server command from the given config object and version // getAPIServerCommand builds the right API server command from the given config object and version
func getAPIServerCommand(cfg *kubeadmapi.ClusterConfiguration, localAPIEndpoint *kubeadmapi.APIEndpoint) []string { func getAPIServerCommand(cfg *kubeadmapi.ClusterConfiguration, localAPIEndpoint *kubeadmapi.APIEndpoint) []string {
defaultArguments := map[string]string{ defaultArguments := []kubeadmapi.Arg{
"advertise-address": localAPIEndpoint.AdvertiseAddress, {Name: "advertise-address", Value: localAPIEndpoint.AdvertiseAddress},
"enable-admission-plugins": "NodeRestriction", {Name: "enable-admission-plugins", Value: "NodeRestriction"},
"service-cluster-ip-range": cfg.Networking.ServiceSubnet, {Name: "service-cluster-ip-range", Value: cfg.Networking.ServiceSubnet},
"service-account-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName), {Name: "service-account-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName)},
"service-account-signing-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName), {Name: "service-account-signing-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName)},
"service-account-issuer": fmt.Sprintf("https://kubernetes.default.svc.%s", cfg.Networking.DNSDomain), {Name: "service-account-issuer", Value: fmt.Sprintf("https://kubernetes.default.svc.%s", cfg.Networking.DNSDomain)},
"client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), {Name: "client-ca-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName)},
"tls-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerCertName), {Name: "tls-cert-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerCertName)},
"tls-private-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKeyName), {Name: "tls-private-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKeyName)},
"kubelet-client-certificate": filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientCertName), {Name: "kubelet-client-certificate", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientCertName)},
"kubelet-client-key": filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientKeyName), {Name: "kubelet-client-key", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientKeyName)},
"enable-bootstrap-token-auth": "true", {Name: "enable-bootstrap-token-auth", Value: "true"},
"secure-port": fmt.Sprintf("%d", localAPIEndpoint.BindPort), {Name: "secure-port", Value: fmt.Sprintf("%d", localAPIEndpoint.BindPort)},
"allow-privileged": "true", {Name: "allow-privileged", Value: "true"},
"kubelet-preferred-address-types": "InternalIP,ExternalIP,Hostname", {Name: "kubelet-preferred-address-types", Value: "InternalIP,ExternalIP,Hostname"},
// add options to configure the front proxy. Without the generated client cert, this will never be useable // add options to configure the front proxy. Without the generated client cert, this will never be useable
// so add it unconditionally with recommended values // so add it unconditionally with recommended values
"requestheader-username-headers": "X-Remote-User", {Name: "requestheader-username-headers", Value: "X-Remote-User"},
"requestheader-group-headers": "X-Remote-Group", {Name: "requestheader-group-headers", Value: "X-Remote-Group"},
"requestheader-extra-headers-prefix": "X-Remote-Extra-", {Name: "requestheader-extra-headers-prefix", Value: "X-Remote-Extra-"},
"requestheader-client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName), {Name: "requestheader-client-ca-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName)},
"requestheader-allowed-names": "front-proxy-client", {Name: "requestheader-allowed-names", Value: "front-proxy-client"},
"proxy-client-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientCertName), {Name: "proxy-client-cert-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientCertName)},
"proxy-client-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName), {Name: "proxy-client-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName)},
} }
command := []string{"kube-apiserver"} command := []string{"kube-apiserver"}
// If the user set endpoints for an external etcd cluster // If the user set endpoints for an external etcd cluster
if cfg.Etcd.External != nil { if cfg.Etcd.External != nil {
defaultArguments["etcd-servers"] = strings.Join(cfg.Etcd.External.Endpoints, ",") defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-servers", strings.Join(cfg.Etcd.External.Endpoints, ","), 1)
// Use any user supplied etcd certificates // Use any user supplied etcd certificates
if cfg.Etcd.External.CAFile != "" { if cfg.Etcd.External.CAFile != "" {
defaultArguments["etcd-cafile"] = cfg.Etcd.External.CAFile defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-cafile", cfg.Etcd.External.CAFile, 1)
} }
if cfg.Etcd.External.CertFile != "" && cfg.Etcd.External.KeyFile != "" { if cfg.Etcd.External.CertFile != "" && cfg.Etcd.External.KeyFile != "" {
defaultArguments["etcd-certfile"] = cfg.Etcd.External.CertFile defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-certfile", cfg.Etcd.External.CertFile, 1)
defaultArguments["etcd-keyfile"] = cfg.Etcd.External.KeyFile defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-keyfile", cfg.Etcd.External.KeyFile, 1)
} }
} else { } else {
// Default to etcd static pod on localhost // Default to etcd static pod on localhost
@ -210,24 +211,25 @@ func getAPIServerCommand(cfg *kubeadmapi.ClusterConfiguration, localAPIEndpoint
if utilsnet.IsIPv6String(localAPIEndpoint.AdvertiseAddress) { if utilsnet.IsIPv6String(localAPIEndpoint.AdvertiseAddress) {
etcdLocalhostAddress = "::1" etcdLocalhostAddress = "::1"
} }
defaultArguments["etcd-servers"] = fmt.Sprintf("https://%s", net.JoinHostPort(etcdLocalhostAddress, strconv.Itoa(kubeadmconstants.EtcdListenClientPort))) defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-servers", fmt.Sprintf("https://%s", net.JoinHostPort(etcdLocalhostAddress, strconv.Itoa(kubeadmconstants.EtcdListenClientPort))), 1)
defaultArguments["etcd-cafile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName) defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-cafile", filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), 1)
defaultArguments["etcd-certfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName) defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-certfile", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName), 1)
defaultArguments["etcd-keyfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName) defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-keyfile", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName), 1)
// Apply user configurations for local etcd // Apply user configurations for local etcd
if cfg.Etcd.Local != nil { if cfg.Etcd.Local != nil {
if value, ok := cfg.Etcd.Local.ExtraArgs["advertise-client-urls"]; ok { if value, idx := kubeadmapi.GetArgValue(cfg.Etcd.Local.ExtraArgs, "advertise-client-urls", -1); idx > -1 {
defaultArguments["etcd-servers"] = value defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "etcd-servers", value, 1)
} }
} }
} }
if cfg.APIServer.ExtraArgs == nil { if cfg.APIServer.ExtraArgs == nil {
cfg.APIServer.ExtraArgs = map[string]string{} cfg.APIServer.ExtraArgs = []kubeadmapi.Arg{}
} }
cfg.APIServer.ExtraArgs["authorization-mode"] = getAuthzModes(cfg.APIServer.ExtraArgs["authorization-mode"]) authzVal, _ := kubeadmapi.GetArgValue(cfg.APIServer.ExtraArgs, "authorization-mode", -1)
command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.APIServer.ExtraArgs)...) cfg.APIServer.ExtraArgs = kubeadmapi.SetArgValues(cfg.APIServer.ExtraArgs, "authorization-mode", getAuthzModes(authzVal), 1)
command = append(command, kubeadmutil.ArgumentsToCommand(defaultArguments, cfg.APIServer.ExtraArgs)...)
return command return command
} }
@ -302,46 +304,46 @@ func getControllerManagerCommand(cfg *kubeadmapi.ClusterConfiguration) []string
kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName) kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName)
caFile := filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName) caFile := filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName)
defaultArguments := map[string]string{ defaultArguments := []kubeadmapi.Arg{
"bind-address": "127.0.0.1", {Name: "bind-address", Value: "127.0.0.1"},
"leader-elect": "true", {Name: "leader-elect", Value: "true"},
"kubeconfig": kubeconfigFile, {Name: "kubeconfig", Value: kubeconfigFile},
"authentication-kubeconfig": kubeconfigFile, {Name: "authentication-kubeconfig", Value: kubeconfigFile},
"authorization-kubeconfig": kubeconfigFile, {Name: "authorization-kubeconfig", Value: kubeconfigFile},
"client-ca-file": caFile, {Name: "client-ca-file", Value: caFile},
"requestheader-client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName), {Name: "requestheader-client-ca-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName)},
"root-ca-file": caFile, {Name: "root-ca-file", Value: caFile},
"service-account-private-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName), {Name: "service-account-private-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName)},
"cluster-signing-cert-file": caFile, {Name: "cluster-signing-cert-file", Value: caFile},
"cluster-signing-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName), {Name: "cluster-signing-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName)},
"use-service-account-credentials": "true", {Name: "use-service-account-credentials", Value: "true"},
"controllers": "*,bootstrapsigner,tokencleaner", {Name: "controllers", Value: "*,bootstrapsigner,tokencleaner"},
} }
// If using external CA, pass empty string to controller manager instead of ca.key/ca.crt path, // If using external CA, pass empty string to controller manager instead of ca.key/ca.crt path,
// so that the csrsigning controller fails to start // so that the csrsigning controller fails to start
if res, _ := certphase.UsingExternalCA(cfg); res { if res, _ := certphase.UsingExternalCA(cfg); res {
defaultArguments["cluster-signing-key-file"] = "" defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "cluster-signing-key-file", "", 1)
defaultArguments["cluster-signing-cert-file"] = "" defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "cluster-signing-cert-file", "", 1)
} }
// Let the controller-manager allocate Node CIDRs for the Pod network. // Let the controller-manager allocate Node CIDRs for the Pod network.
// Each node will get a subspace of the address CIDR provided with --pod-network-cidr. // Each node will get a subspace of the address CIDR provided with --pod-network-cidr.
if cfg.Networking.PodSubnet != "" { if cfg.Networking.PodSubnet != "" {
defaultArguments["allocate-node-cidrs"] = "true" defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "allocate-node-cidrs", "true", 1)
defaultArguments["cluster-cidr"] = cfg.Networking.PodSubnet defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "cluster-cidr", cfg.Networking.PodSubnet, 1)
if cfg.Networking.ServiceSubnet != "" { if cfg.Networking.ServiceSubnet != "" {
defaultArguments["service-cluster-ip-range"] = cfg.Networking.ServiceSubnet defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "service-cluster-ip-range", cfg.Networking.ServiceSubnet, 1)
} }
} }
// Set cluster name // Set cluster name
if cfg.ClusterName != "" { if cfg.ClusterName != "" {
defaultArguments["cluster-name"] = cfg.ClusterName defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "cluster-name", cfg.ClusterName, 1)
} }
command := []string{"kube-controller-manager"} command := []string{"kube-controller-manager"}
command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.ControllerManager.ExtraArgs)...) command = append(command, kubeadmutil.ArgumentsToCommand(defaultArguments, cfg.ControllerManager.ExtraArgs)...)
return command return command
} }
@ -349,15 +351,15 @@ func getControllerManagerCommand(cfg *kubeadmapi.ClusterConfiguration) []string
// getSchedulerCommand builds the right scheduler command from the given config object and version // getSchedulerCommand builds the right scheduler command from the given config object and version
func getSchedulerCommand(cfg *kubeadmapi.ClusterConfiguration) []string { func getSchedulerCommand(cfg *kubeadmapi.ClusterConfiguration) []string {
kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName) kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName)
defaultArguments := map[string]string{ defaultArguments := []kubeadmapi.Arg{
"bind-address": "127.0.0.1", {Name: "bind-address", Value: "127.0.0.1"},
"leader-elect": "true", {Name: "leader-elect", Value: "true"},
"kubeconfig": kubeconfigFile, {Name: "kubeconfig", Value: kubeconfigFile},
"authentication-kubeconfig": kubeconfigFile, {Name: "authentication-kubeconfig", Value: kubeconfigFile},
"authorization-kubeconfig": kubeconfigFile, {Name: "authorization-kubeconfig", Value: kubeconfigFile},
} }
command := []string{"kube-scheduler"} command := []string{"kube-scheduler"}
command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.Scheduler.ExtraArgs)...) command = append(command, kubeadmutil.ArgumentsToCommand(defaultArguments, cfg.Scheduler.ExtraArgs)...)
return command return command
} }

View File

@ -375,11 +375,11 @@ func TestGetAPIServerCommand(t *testing.T) {
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
APIServer: kubeadmapi.APIServer{ APIServer: kubeadmapi.APIServer{
ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{ ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"service-cluster-ip-range": "baz", {Name: "service-cluster-ip-range", Value: "baz"},
"advertise-address": "9.9.9.9", {Name: "advertise-address", Value: "9.9.9.9"},
"audit-policy-file": "/etc/config/audit.yaml", {Name: "audit-policy-file", Value: "/etc/config/audit.yaml"},
"audit-log-path": "/var/log/kubernetes", {Name: "audit-log-path", Value: "/var/log/kubernetes"},
}, },
}, },
}, },
@ -425,8 +425,8 @@ func TestGetAPIServerCommand(t *testing.T) {
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
APIServer: kubeadmapi.APIServer{ APIServer: kubeadmapi.APIServer{
ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{ ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"authorization-mode": kubeadmconstants.ModeABAC, {Name: "authorization-mode", Value: kubeadmconstants.ModeABAC},
}, },
}, },
}, },
@ -470,12 +470,12 @@ func TestGetAPIServerCommand(t *testing.T) {
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
APIServer: kubeadmapi.APIServer{ APIServer: kubeadmapi.APIServer{
ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{ ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"authorization-mode": strings.Join([]string{ {Name: "authorization-mode", Value: strings.Join([]string{
kubeadmconstants.ModeNode, kubeadmconstants.ModeNode,
kubeadmconstants.ModeRBAC, kubeadmconstants.ModeRBAC,
kubeadmconstants.ModeWebhook, kubeadmconstants.ModeWebhook,
}, ","), }, ",")},
}, },
}, },
}, },
@ -660,7 +660,7 @@ func TestGetControllerManagerCommand(t *testing.T) {
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16", DNSDomain: "cluster.local"}, Networking: kubeadmapi.Networking{PodSubnet: "10.0.1.15/16", DNSDomain: "cluster.local"},
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{"node-cidr-mask-size": "20"}, ExtraArgs: []kubeadmapi.Arg{{Name: "node-cidr-mask-size", Value: "20"}},
}, },
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
KubernetesVersion: cpVersion, KubernetesVersion: cpVersion,
@ -726,7 +726,7 @@ func TestGetControllerManagerCommand(t *testing.T) {
DNSDomain: "cluster.local", DNSDomain: "cluster.local",
}, },
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{"allocate-node-cidrs": "false"}, ExtraArgs: []kubeadmapi.Arg{{Name: "allocate-node-cidrs", Value: "false"}},
}, },
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
KubernetesVersion: cpVersion, KubernetesVersion: cpVersion,
@ -790,7 +790,10 @@ func TestGetControllerManagerCommand(t *testing.T) {
DNSDomain: "cluster.local", DNSDomain: "cluster.local",
}, },
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{"node-cidr-mask-size-ipv4": "20", "node-cidr-mask-size-ipv6": "80"}, ExtraArgs: []kubeadmapi.Arg{
{Name: "node-cidr-mask-size-ipv4", Value: "20"},
{Name: "node-cidr-mask-size-ipv6", Value: "80"},
},
}, },
CertificatesDir: testCertsDir, CertificatesDir: testCertsDir,
KubernetesVersion: cpVersion, KubernetesVersion: cpVersion,

View File

@ -72,8 +72,8 @@ func getHostPathVolumesForTheControlPlane(cfg *kubeadmapi.ClusterConfiguration)
mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true, &hostPathFileOrCreate) mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, kubeadmconstants.KubeConfigVolumeName, controllerManagerKubeConfigFile, controllerManagerKubeConfigFile, true, &hostPathFileOrCreate)
// Mount for the flexvolume directory (/usr/libexec/kubernetes/kubelet-plugins/volume/exec by default) // Mount for the flexvolume directory (/usr/libexec/kubernetes/kubelet-plugins/volume/exec by default)
// Flexvolume dir must NOT be readonly as it is used for third-party plugins to integrate with their storage backends via unix domain socket. // Flexvolume dir must NOT be readonly as it is used for third-party plugins to integrate with their storage backends via unix domain socket.
flexvolumeDirVolumePath, ok := cfg.ControllerManager.ExtraArgs["flex-volume-plugin-dir"] flexvolumeDirVolumePath, idx := kubeadmapi.GetArgValue(cfg.ControllerManager.ExtraArgs, "flex-volume-plugin-dir", -1)
if !ok { if idx == -1 {
flexvolumeDirVolumePath = defaultFlexvolumeDirVolumePath flexvolumeDirVolumePath = defaultFlexvolumeDirVolumePath
} }
mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, flexvolumeDirVolumeName, flexvolumeDirVolumePath, flexvolumeDirVolumePath, false, &hostPathDirectoryOrCreate) mounts.NewHostPathMount(kubeadmconstants.KubeControllerManager, flexvolumeDirVolumeName, flexvolumeDirVolumePath, flexvolumeDirVolumePath, false, &hostPathDirectoryOrCreate)

View File

@ -239,31 +239,31 @@ func getEtcdCommand(cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.A
if utilsnet.IsIPv6String(endpoint.AdvertiseAddress) { if utilsnet.IsIPv6String(endpoint.AdvertiseAddress) {
etcdLocalhostAddress = "::1" etcdLocalhostAddress = "::1"
} }
defaultArguments := map[string]string{ defaultArguments := []kubeadmapi.Arg{
"name": nodeName, {Name: "name", Value: nodeName},
// TODO: start using --initial-corrupt-check once the graduated flag is available: // TODO: start using --initial-corrupt-check once the graduated flag is available,
// https://github.com/kubernetes/kubeadm/issues/2676 // https://github.com/kubernetes/kubeadm/issues/2676
"experimental-initial-corrupt-check": "true", {Name: "experimental-initial-corrupt-check", Value: "true"},
"listen-client-urls": fmt.Sprintf("%s,%s", etcdutil.GetClientURLByIP(etcdLocalhostAddress), etcdutil.GetClientURL(endpoint)), {Name: "listen-client-urls", Value: fmt.Sprintf("%s,%s", etcdutil.GetClientURLByIP(etcdLocalhostAddress), etcdutil.GetClientURL(endpoint))},
"advertise-client-urls": etcdutil.GetClientURL(endpoint), {Name: "advertise-client-urls", Value: etcdutil.GetClientURL(endpoint)},
"listen-peer-urls": etcdutil.GetPeerURL(endpoint), {Name: "listen-peer-urls", Value: etcdutil.GetPeerURL(endpoint)},
"initial-advertise-peer-urls": etcdutil.GetPeerURL(endpoint), {Name: "initial-advertise-peer-urls", Value: etcdutil.GetPeerURL(endpoint)},
"data-dir": cfg.Etcd.Local.DataDir, {Name: "data-dir", Value: cfg.Etcd.Local.DataDir},
"cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName), {Name: "cert-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerCertName)},
"key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName), {Name: "key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName)},
"trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), {Name: "trusted-ca-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName)},
"client-cert-auth": "true", {Name: "client-cert-auth", Value: "true"},
"peer-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName), {Name: "peer-cert-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerCertName)},
"peer-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName), {Name: "peer-key-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName)},
"peer-trusted-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName), {Name: "peer-trusted-ca-file", Value: filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName)},
"peer-client-cert-auth": "true", {Name: "peer-client-cert-auth", Value: "true"},
"snapshot-count": "10000", {Name: "snapshot-count", Value: "10000"},
"listen-metrics-urls": fmt.Sprintf("http://%s", net.JoinHostPort(etcdLocalhostAddress, strconv.Itoa(kubeadmconstants.EtcdMetricsPort))), {Name: "listen-metrics-urls", Value: fmt.Sprintf("http://%s", net.JoinHostPort(etcdLocalhostAddress, strconv.Itoa(kubeadmconstants.EtcdMetricsPort)))},
"experimental-watch-progress-notify-interval": "5s", {Name: "experimental-watch-progress-notify-interval", Value: "5s"},
} }
if len(initialCluster) == 0 { if len(initialCluster) == 0 {
defaultArguments["initial-cluster"] = fmt.Sprintf("%s=%s", nodeName, etcdutil.GetPeerURL(endpoint)) defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "initial-cluster", fmt.Sprintf("%s=%s", nodeName, etcdutil.GetPeerURL(endpoint)), 1)
} else { } else {
// NB. the joining etcd member should be part of the initialCluster list // NB. the joining etcd member should be part of the initialCluster list
endpoints := []string{} endpoints := []string{}
@ -271,12 +271,12 @@ func getEtcdCommand(cfg *kubeadmapi.ClusterConfiguration, endpoint *kubeadmapi.A
endpoints = append(endpoints, fmt.Sprintf("%s=%s", member.Name, member.PeerURL)) endpoints = append(endpoints, fmt.Sprintf("%s=%s", member.Name, member.PeerURL))
} }
defaultArguments["initial-cluster"] = strings.Join(endpoints, ",") defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "initial-cluster", strings.Join(endpoints, ","), 1)
defaultArguments["initial-cluster-state"] = "existing" defaultArguments = kubeadmapi.SetArgValues(defaultArguments, "initial-cluster-state", "existing", 1)
} }
command := []string{"etcd"} command := []string{"etcd"}
command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.Etcd.Local.ExtraArgs)...) command = append(command, kubeadmutil.ArgumentsToCommand(defaultArguments, cfg.Etcd.Local.ExtraArgs)...)
return command return command
} }

View File

@ -176,7 +176,7 @@ func TestGetEtcdCommand(t *testing.T) {
name string name string
advertiseAddress string advertiseAddress string
nodeName string nodeName string
extraArgs map[string]string extraArgs []kubeadmapi.Arg
initialCluster []etcdutil.Member initialCluster []etcdutil.Member
expected []string expected []string
}{ }{
@ -243,9 +243,9 @@ func TestGetEtcdCommand(t *testing.T) {
name: "Extra args", name: "Extra args",
advertiseAddress: "1.2.3.4", advertiseAddress: "1.2.3.4",
nodeName: "bar", nodeName: "bar",
extraArgs: map[string]string{ extraArgs: []kubeadmapi.Arg{
"listen-client-urls": "https://10.0.1.10:2379", {Name: "listen-client-urls", Value: "https://10.0.1.10:2379"},
"advertise-client-urls": "https://10.0.1.10:2379", {Name: "advertise-client-urls", Value: "https://10.0.1.10:2379"},
}, },
expected: []string{ expected: []string{
"etcd", "etcd",

View File

@ -51,7 +51,7 @@ func GetNodeNameAndHostname(cfg *kubeadmapi.NodeRegistrationOptions) (string, st
if cfg.Name != "" { if cfg.Name != "" {
nodeName = cfg.Name nodeName = cfg.Name
} }
if name, ok := cfg.KubeletExtraArgs["hostname-override"]; ok { if name, idx := kubeadmapi.GetArgValue(cfg.KubeletExtraArgs, "hostname-override", -1); idx > -1 {
nodeName = name nodeName = name
} }
return nodeName, hostname, err return nodeName, hostname, err
@ -65,23 +65,23 @@ func WriteKubeletDynamicEnvFile(cfg *kubeadmapi.ClusterConfiguration, nodeReg *k
pauseImage: images.GetPauseImage(cfg), pauseImage: images.GetPauseImage(cfg),
registerTaintsUsingFlags: registerTaintsUsingFlags, registerTaintsUsingFlags: registerTaintsUsingFlags,
} }
stringMap := buildKubeletArgMap(flagOpts) stringMap := buildKubeletArgs(flagOpts)
argList := kubeadmutil.BuildArgumentListFromMap(stringMap, nodeReg.KubeletExtraArgs) argList := kubeadmutil.ArgumentsToCommand(stringMap, nodeReg.KubeletExtraArgs)
envFileContent := fmt.Sprintf("%s=%q\n", constants.KubeletEnvFileVariableName, strings.Join(argList, " ")) envFileContent := fmt.Sprintf("%s=%q\n", constants.KubeletEnvFileVariableName, strings.Join(argList, " "))
return writeKubeletFlagBytesToDisk([]byte(envFileContent), kubeletDir) return writeKubeletFlagBytesToDisk([]byte(envFileContent), kubeletDir)
} }
// buildKubeletArgMapCommon takes a kubeletFlagsOpts object and builds based on that a string-string map with flags // buildKubeletArgsCommon takes a kubeletFlagsOpts object and builds based on that a slice of arguments
// that are common to both Linux and Windows // that are common to both Linux and Windows
func buildKubeletArgMapCommon(opts kubeletFlagsOpts) map[string]string { func buildKubeletArgsCommon(opts kubeletFlagsOpts) []kubeadmapi.Arg {
kubeletFlags := map[string]string{} kubeletFlags := []kubeadmapi.Arg{}
kubeletFlags["container-runtime-endpoint"] = opts.nodeRegOpts.CRISocket kubeletFlags = append(kubeletFlags, kubeadmapi.Arg{Name: "container-runtime-endpoint", Value: opts.nodeRegOpts.CRISocket})
// This flag passes the pod infra container image (e.g. "pause" image) to the kubelet // This flag passes the pod infra container image (e.g. "pause" image) to the kubelet
// and prevents its garbage collection // and prevents its garbage collection
if opts.pauseImage != "" { if opts.pauseImage != "" {
kubeletFlags["pod-infra-container-image"] = opts.pauseImage kubeletFlags = append(kubeletFlags, kubeadmapi.Arg{Name: "pod-infra-container-image", Value: opts.pauseImage})
} }
if opts.registerTaintsUsingFlags && opts.nodeRegOpts.Taints != nil && len(opts.nodeRegOpts.Taints) > 0 { if opts.registerTaintsUsingFlags && opts.nodeRegOpts.Taints != nil && len(opts.nodeRegOpts.Taints) > 0 {
@ -89,8 +89,7 @@ func buildKubeletArgMapCommon(opts kubeletFlagsOpts) map[string]string {
for _, taint := range opts.nodeRegOpts.Taints { for _, taint := range opts.nodeRegOpts.Taints {
taintStrs = append(taintStrs, taint.ToString()) taintStrs = append(taintStrs, taint.ToString())
} }
kubeletFlags = append(kubeletFlags, kubeadmapi.Arg{Name: "register-with-taints", Value: strings.Join(taintStrs, ",")})
kubeletFlags["register-with-taints"] = strings.Join(taintStrs, ",")
} }
// Pass the "--hostname-override" flag to the kubelet only if it's different from the hostname // Pass the "--hostname-override" flag to the kubelet only if it's different from the hostname
@ -100,7 +99,7 @@ func buildKubeletArgMapCommon(opts kubeletFlagsOpts) map[string]string {
} }
if nodeName != hostname { if nodeName != hostname {
klog.V(1).Infof("setting kubelet hostname-override to %q", nodeName) klog.V(1).Infof("setting kubelet hostname-override to %q", nodeName)
kubeletFlags["hostname-override"] = nodeName kubeletFlags = append(kubeletFlags, kubeadmapi.Arg{Name: "hostname-override", Value: nodeName})
} }
return kubeletFlags return kubeletFlags
@ -121,8 +120,8 @@ func writeKubeletFlagBytesToDisk(b []byte, kubeletDir string) error {
return nil return nil
} }
// buildKubeletArgMap takes a kubeletFlagsOpts object and builds based on that a string-string map with flags // buildKubeletArgs takes a kubeletFlagsOpts object and builds based on that a slice of arguments
// that should be given to the local kubelet daemon. // that should be given to the local kubelet daemon.
func buildKubeletArgMap(opts kubeletFlagsOpts) map[string]string { func buildKubeletArgs(opts kubeletFlagsOpts) []kubeadmapi.Arg {
return buildKubeletArgMapCommon(opts) return buildKubeletArgsCommon(opts)
} }

View File

@ -27,23 +27,25 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
) )
func TestBuildKubeletArgMap(t *testing.T) { func TestBuildKubeletArgs(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
opts kubeletFlagsOpts opts kubeletFlagsOpts
expected map[string]string expected []kubeadmapi.Arg
}{ }{
{ {
name: "hostname override", name: "hostname override",
opts: kubeletFlagsOpts{ opts: kubeletFlagsOpts{
nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{
CRISocket: "unix:///var/run/containerd/containerd.sock", CRISocket: "unix:///var/run/containerd/containerd.sock",
KubeletExtraArgs: map[string]string{"hostname-override": "override-name"}, KubeletExtraArgs: []kubeadmapi.Arg{
{Name: "hostname-override", Value: "override-name"},
}, },
}, },
expected: map[string]string{ },
"container-runtime-endpoint": "unix:///var/run/containerd/containerd.sock", expected: []kubeadmapi.Arg{
"hostname-override": "override-name", {Name: "container-runtime-endpoint", Value: "unix:///var/run/containerd/containerd.sock"},
{Name: "hostname-override", Value: "override-name"},
}, },
}, },
{ {
@ -66,9 +68,9 @@ func TestBuildKubeletArgMap(t *testing.T) {
}, },
registerTaintsUsingFlags: true, registerTaintsUsingFlags: true,
}, },
expected: map[string]string{ expected: []kubeadmapi.Arg{
"container-runtime-endpoint": "unix:///var/run/containerd/containerd.sock", {Name: "container-runtime-endpoint", Value: "unix:///var/run/containerd/containerd.sock"},
"register-with-taints": "foo=bar:baz,key=val:eff", {Name: "register-with-taints", Value: "foo=bar:baz,key=val:eff"},
}, },
}, },
{ {
@ -79,19 +81,19 @@ func TestBuildKubeletArgMap(t *testing.T) {
}, },
pauseImage: "registry.k8s.io/pause:3.9", pauseImage: "registry.k8s.io/pause:3.9",
}, },
expected: map[string]string{ expected: []kubeadmapi.Arg{
"container-runtime-endpoint": "unix:///var/run/containerd/containerd.sock", {Name: "container-runtime-endpoint", Value: "unix:///var/run/containerd/containerd.sock"},
"pod-infra-container-image": "registry.k8s.io/pause:3.9", {Name: "pod-infra-container-image", Value: "registry.k8s.io/pause:3.9"},
}, },
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
actual := buildKubeletArgMap(test.opts) actual := buildKubeletArgs(test.opts)
if !reflect.DeepEqual(actual, test.expected) { if !reflect.DeepEqual(actual, test.expected) {
t.Errorf( t.Errorf(
"failed buildKubeletArgMap:\n\texpected: %v\n\t actual: %v", "failed buildKubeletArgs:\n\texpected: %v\n\t actual: %v",
test.expected, test.expected,
actual, actual,
) )
@ -116,7 +118,9 @@ func TestGetNodeNameAndHostname(t *testing.T) {
name: "overridden hostname", name: "overridden hostname",
opts: kubeletFlagsOpts{ opts: kubeletFlagsOpts{
nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{
KubeletExtraArgs: map[string]string{"hostname-override": "override-name"}, KubeletExtraArgs: []kubeadmapi.Arg{
{Name: "hostname-override", Value: "override-name"},
},
}, },
}, },
expectedNodeName: "override-name", expectedNodeName: "override-name",
@ -126,7 +130,9 @@ func TestGetNodeNameAndHostname(t *testing.T) {
name: "overridden hostname uppercase", name: "overridden hostname uppercase",
opts: kubeletFlagsOpts{ opts: kubeletFlagsOpts{
nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{
KubeletExtraArgs: map[string]string{"hostname-override": "OVERRIDE-NAME"}, KubeletExtraArgs: []kubeadmapi.Arg{
{Name: "hostname-override", Value: "OVERRIDE-NAME"},
},
}, },
}, },
expectedNodeName: "OVERRIDE-NAME", expectedNodeName: "OVERRIDE-NAME",
@ -136,7 +142,9 @@ func TestGetNodeNameAndHostname(t *testing.T) {
name: "hostname contains only spaces", name: "hostname contains only spaces",
opts: kubeletFlagsOpts{ opts: kubeletFlagsOpts{
nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{
KubeletExtraArgs: map[string]string{"hostname-override": " "}, KubeletExtraArgs: []kubeadmapi.Arg{
{Name: "hostname-override", Value: " "},
},
}, },
}, },
expectedNodeName: " ", expectedNodeName: " ",
@ -146,7 +154,9 @@ func TestGetNodeNameAndHostname(t *testing.T) {
name: "empty parameter", name: "empty parameter",
opts: kubeletFlagsOpts{ opts: kubeletFlagsOpts{
nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{ nodeRegOpts: &kubeadmapi.NodeRegistrationOptions{
KubeletExtraArgs: map[string]string{"hostname-override": ""}, KubeletExtraArgs: []kubeadmapi.Arg{
{Name: "hostname-override", Value: ""},
},
}, },
}, },
expectedNodeName: "", expectedNodeName: "",

View File

@ -295,7 +295,7 @@ func GetAPIServerProbeAddress(endpoint *kubeadmapi.APIEndpoint) string {
// GetControllerManagerProbeAddress returns the kubernetes controller manager probe address // GetControllerManagerProbeAddress returns the kubernetes controller manager probe address
func GetControllerManagerProbeAddress(cfg *kubeadmapi.ClusterConfiguration) string { func GetControllerManagerProbeAddress(cfg *kubeadmapi.ClusterConfiguration) string {
if addr, exists := cfg.ControllerManager.ExtraArgs[kubeControllerManagerBindAddressArg]; exists { if addr, idx := kubeadmapi.GetArgValue(cfg.ControllerManager.ExtraArgs, kubeControllerManagerBindAddressArg, -1); idx > -1 {
return getProbeAddress(addr) return getProbeAddress(addr)
} }
return "127.0.0.1" return "127.0.0.1"
@ -303,7 +303,7 @@ func GetControllerManagerProbeAddress(cfg *kubeadmapi.ClusterConfiguration) stri
// GetSchedulerProbeAddress returns the kubernetes scheduler probe address // GetSchedulerProbeAddress returns the kubernetes scheduler probe address
func GetSchedulerProbeAddress(cfg *kubeadmapi.ClusterConfiguration) string { func GetSchedulerProbeAddress(cfg *kubeadmapi.ClusterConfiguration) string {
if addr, exists := cfg.Scheduler.ExtraArgs[kubeSchedulerBindAddressArg]; exists { if addr, idx := kubeadmapi.GetArgValue(cfg.Scheduler.ExtraArgs, kubeSchedulerBindAddressArg, -1); idx > -1 {
return getProbeAddress(addr) return getProbeAddress(addr)
} }
return "127.0.0.1" return "127.0.0.1"
@ -320,7 +320,7 @@ func GetEtcdProbeEndpoint(cfg *kubeadmapi.Etcd, isIPv6 bool) (string, int, v1.UR
if cfg.Local == nil || cfg.Local.ExtraArgs == nil { if cfg.Local == nil || cfg.Local.ExtraArgs == nil {
return localhost, kubeadmconstants.EtcdMetricsPort, v1.URISchemeHTTP return localhost, kubeadmconstants.EtcdMetricsPort, v1.URISchemeHTTP
} }
if arg, exists := cfg.Local.ExtraArgs["listen-metrics-urls"]; exists { if arg, idx := kubeadmapi.GetArgValue(cfg.Local.ExtraArgs, "listen-metrics-urls", -1); idx > -1 {
// Use the first url in the listen-metrics-urls if multiple URL's are specified. // Use the first url in the listen-metrics-urls if multiple URL's are specified.
arg = strings.Split(arg, ",")[0] arg = strings.Split(arg, ",")[0]
parsedURL, err := url.Parse(arg) parsedURL, err := url.Parse(arg)

View File

@ -107,7 +107,7 @@ func TestGetControllerManagerProbeAddress(t *testing.T) {
desc: "no controller manager extra args leads to 127.0.0.1 being used", desc: "no controller manager extra args leads to 127.0.0.1 being used",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{}, ExtraArgs: []kubeadmapi.Arg{},
}, },
}, },
expected: "127.0.0.1", expected: "127.0.0.1",
@ -116,8 +116,8 @@ func TestGetControllerManagerProbeAddress(t *testing.T) {
desc: "setting controller manager extra address arg to something acknowledges it", desc: "setting controller manager extra address arg to something acknowledges it",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeControllerManagerBindAddressArg: "10.10.10.10", {Name: kubeControllerManagerBindAddressArg, Value: "10.10.10.10"},
}, },
}, },
}, },
@ -127,8 +127,8 @@ func TestGetControllerManagerProbeAddress(t *testing.T) {
desc: "setting controller manager extra ipv6 address arg to something acknowledges it", desc: "setting controller manager extra ipv6 address arg to something acknowledges it",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeControllerManagerBindAddressArg: "2001:abcd:bcda::1", {Name: kubeControllerManagerBindAddressArg, Value: "2001:abcd:bcda::1"},
}, },
}, },
}, },
@ -138,8 +138,8 @@ func TestGetControllerManagerProbeAddress(t *testing.T) {
desc: "setting controller manager extra address arg to 0.0.0.0 returns empty", desc: "setting controller manager extra address arg to 0.0.0.0 returns empty",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeControllerManagerBindAddressArg: "0.0.0.0", {Name: kubeControllerManagerBindAddressArg, Value: "0.0.0.0"},
}, },
}, },
}, },
@ -149,8 +149,8 @@ func TestGetControllerManagerProbeAddress(t *testing.T) {
desc: "setting controller manager extra ipv6 address arg to :: returns empty", desc: "setting controller manager extra ipv6 address arg to :: returns empty",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
ControllerManager: kubeadmapi.ControlPlaneComponent{ ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeControllerManagerBindAddressArg: "::", {Name: kubeControllerManagerBindAddressArg, Value: "::"},
}, },
}, },
}, },
@ -178,7 +178,7 @@ func TestGetSchedulerProbeAddress(t *testing.T) {
desc: "no scheduler extra args leads to 127.0.0.1 being used", desc: "no scheduler extra args leads to 127.0.0.1 being used",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Scheduler: kubeadmapi.ControlPlaneComponent{ Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{}, ExtraArgs: []kubeadmapi.Arg{},
}, },
}, },
expected: "127.0.0.1", expected: "127.0.0.1",
@ -187,8 +187,8 @@ func TestGetSchedulerProbeAddress(t *testing.T) {
desc: "setting scheduler extra address arg to something acknowledges it", desc: "setting scheduler extra address arg to something acknowledges it",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Scheduler: kubeadmapi.ControlPlaneComponent{ Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeSchedulerBindAddressArg: "10.10.10.10", {Name: kubeSchedulerBindAddressArg, Value: "10.10.10.10"},
}, },
}, },
}, },
@ -198,8 +198,8 @@ func TestGetSchedulerProbeAddress(t *testing.T) {
desc: "setting scheduler extra ipv6 address arg to something acknowledges it", desc: "setting scheduler extra ipv6 address arg to something acknowledges it",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Scheduler: kubeadmapi.ControlPlaneComponent{ Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeSchedulerBindAddressArg: "2001:abcd:bcda::1", {Name: kubeSchedulerBindAddressArg, Value: "2001:abcd:bcda::1"},
}, },
}, },
}, },
@ -209,8 +209,8 @@ func TestGetSchedulerProbeAddress(t *testing.T) {
desc: "setting scheduler extra ipv6 address arg to 0.0.0.0 returns empty", desc: "setting scheduler extra ipv6 address arg to 0.0.0.0 returns empty",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Scheduler: kubeadmapi.ControlPlaneComponent{ Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeSchedulerBindAddressArg: "0.0.0.0", {Name: kubeSchedulerBindAddressArg, Value: "0.0.0.0"},
}, },
}, },
}, },
@ -220,8 +220,8 @@ func TestGetSchedulerProbeAddress(t *testing.T) {
desc: "setting scheduler extra ipv6 address arg to :: returns empty", desc: "setting scheduler extra ipv6 address arg to :: returns empty",
cfg: &kubeadmapi.ClusterConfiguration{ cfg: &kubeadmapi.ClusterConfiguration{
Scheduler: kubeadmapi.ControlPlaneComponent{ Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
kubeSchedulerBindAddressArg: "::", {Name: kubeSchedulerBindAddressArg, Value: "::"},
}, },
}, },
}, },
@ -251,8 +251,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe URL from two URLs", name: "etcd probe URL from two URLs",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "https://1.2.3.4:1234,https://4.3.2.1:2381"}, {Name: "listen-metrics-urls", Value: "https://1.2.3.4:1234,https://4.3.2.1:2381"},
},
}, },
}, },
isIPv6: false, isIPv6: false,
@ -264,8 +265,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe URL with HTTP scheme", name: "etcd probe URL with HTTP scheme",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "http://1.2.3.4:1234"}, {Name: "listen-metrics-urls", Value: "http://1.2.3.4:1234"},
},
}, },
}, },
isIPv6: false, isIPv6: false,
@ -277,8 +279,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe URL without scheme should result in defaults", name: "etcd probe URL without scheme should result in defaults",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "1.2.3.4"}, {Name: "listen-metrics-urls", Value: "1.2.3.4"},
},
}, },
}, },
isIPv6: false, isIPv6: false,
@ -290,8 +293,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe URL without port", name: "etcd probe URL without port",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "https://1.2.3.4"}, {Name: "listen-metrics-urls", Value: "https://1.2.3.4"},
},
}, },
}, },
isIPv6: false, isIPv6: false,
@ -303,8 +307,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe URL from two IPv6 URLs", name: "etcd probe URL from two IPv6 URLs",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "https://[2001:abcd:bcda::1]:1234,https://[2001:abcd:bcda::2]:2381"}, {Name: "listen-metrics-urls", Value: "https://[2001:abcd:bcda::1]:1234,https://[2001:abcd:bcda::2]:2381"},
},
}, },
}, },
isIPv6: true, isIPv6: true,
@ -316,8 +321,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe localhost IPv6 URL with HTTP scheme", name: "etcd probe localhost IPv6 URL with HTTP scheme",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "http://[::1]:1234"}, {Name: "listen-metrics-urls", Value: "http://[::1]:1234"},
},
}, },
}, },
isIPv6: true, isIPv6: true,
@ -329,8 +335,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe IPv6 URL with HTTP scheme", name: "etcd probe IPv6 URL with HTTP scheme",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "http://[2001:abcd:bcda::1]:1234"}, {Name: "listen-metrics-urls", Value: "http://[2001:abcd:bcda::1]:1234"},
},
}, },
}, },
isIPv6: true, isIPv6: true,
@ -342,8 +349,9 @@ func TestGetEtcdProbeEndpoint(t *testing.T) {
name: "etcd probe IPv6 URL without port", name: "etcd probe IPv6 URL without port",
cfg: &kubeadmapi.Etcd{ cfg: &kubeadmapi.Etcd{
Local: &kubeadmapi.LocalEtcd{ Local: &kubeadmapi.LocalEtcd{
ExtraArgs: map[string]string{ ExtraArgs: []kubeadmapi.Arg{
"listen-metrics-urls": "https://[2001:abcd:bcda::1]"}, {Name: "listen-metrics-urls", Value: "https://[2001:abcd:bcda::1]"},
},
}, },
}, },
isIPv6: true, isIPv6: true,