From 6fecfe6ea62b3c3758316db3712e6acb27978b44 Mon Sep 17 00:00:00 2001 From: Chuck Ha Date: Wed, 25 Apr 2018 11:49:22 +0100 Subject: [PATCH] Correctly override args with APIServerExtraArgs Removes an unused parameter in getAPIServerCommand Cleans up tests by: * Naming the tests * Using t.Run for better test output * Removing duplicates Fixes kubernets/kubeadm#760 Signed-off-by: Chuck Ha --- .../app/phases/controlplane/manifests.go | 44 ++- .../app/phases/controlplane/manifests_test.go | 344 ++++++++---------- 2 files changed, 163 insertions(+), 225 deletions(-) diff --git a/cmd/kubeadm/app/phases/controlplane/manifests.go b/cmd/kubeadm/app/phases/controlplane/manifests.go index 30c73491efd..1019660ba4d 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests.go @@ -86,7 +86,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version. Name: kubeadmconstants.KubeAPIServer, Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage), ImagePullPolicy: cfg.ImagePullPolicy, - Command: getAPIServerCommand(cfg, k8sVersion), + Command: getAPIServerCommand(cfg), VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer)), LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeAPIServer, int(cfg.API.BindPort), "/healthz", v1.URISchemeHTTPS), Resources: staticpodutil.ComponentResources("250m"), @@ -161,7 +161,7 @@ func createStaticPodFiles(manifestDir string, cfg *kubeadmapi.MasterConfiguratio } // getAPIServerCommand builds the right API server command from the given config object and version -func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.Version) []string { +func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration) []string { defaultArguments := map[string]string{ "advertise-address": cfg.API.AdvertiseAddress, "insecure-port": "0", @@ -194,29 +194,24 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *versio defaultArguments["admission-control"] = deprecatedV19AdmissionControl } - command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.APIServerExtraArgs)...) - command = append(command, getAuthzParameters(cfg.AuthorizationModes)...) - // If the user set endpoints for an external etcd cluster if len(cfg.Etcd.Endpoints) > 0 { - command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(cfg.Etcd.Endpoints, ","))) + defaultArguments["etcd-servers"] = strings.Join(cfg.Etcd.Endpoints, ",") // Use any user supplied etcd certificates if cfg.Etcd.CAFile != "" { - command = append(command, fmt.Sprintf("--etcd-cafile=%s", cfg.Etcd.CAFile)) + defaultArguments["etcd-cafile"] = cfg.Etcd.CAFile } if cfg.Etcd.CertFile != "" && cfg.Etcd.KeyFile != "" { - etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", cfg.Etcd.CertFile) - etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", cfg.Etcd.KeyFile) - command = append(command, etcdClientFileArg, etcdKeyFileArg) + defaultArguments["etcd-certfile"] = cfg.Etcd.CertFile + defaultArguments["etcd-keyfile"] = cfg.Etcd.KeyFile } } else { // Default to etcd static pod on localhost - etcdEndpointsArg := "--etcd-servers=https://127.0.0.1:2379" - etcdCAFileArg := fmt.Sprintf("--etcd-cafile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName)) - etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName)) - etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName)) - command = append(command, etcdEndpointsArg, etcdCAFileArg, etcdClientFileArg, etcdKeyFileArg) + defaultArguments["etcd-servers"] = "https://127.0.0.1:2379" + defaultArguments["etcd-cafile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCACertName) + defaultArguments["etcd-certfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientCertName) + defaultArguments["etcd-keyfile"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName) // Warn for unused user supplied variables if cfg.Etcd.CAFile != "" { @@ -231,32 +226,35 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, k8sVersion *versio } if cfg.CloudProvider != "" { - command = append(command, "--cloud-provider="+cfg.CloudProvider) + defaultArguments["cloud-provider"] = cfg.CloudProvider // Only append the --cloud-config option if there's a such file if _, err := os.Stat(DefaultCloudConfigPath); err == nil { - command = append(command, "--cloud-config="+DefaultCloudConfigPath) + defaultArguments["cloud-config"] = DefaultCloudConfigPath } } if features.Enabled(cfg.FeatureGates, features.HighAvailability) { - command = append(command, "--endpoint-reconciler-type="+reconcilers.LeaseEndpointReconcilerType) + defaultArguments["endpoint-reconciler-type"] = reconcilers.LeaseEndpointReconcilerType } if features.Enabled(cfg.FeatureGates, features.DynamicKubeletConfig) { - command = append(command, "--feature-gates=DynamicKubeletConfig=true") + defaultArguments["feature-gates"] = "DynamicKubeletConfig=true" } if features.Enabled(cfg.FeatureGates, features.Auditing) { - command = append(command, "--audit-policy-file="+kubeadmconstants.GetStaticPodAuditPolicyFile()) - command = append(command, "--audit-log-path="+filepath.Join(kubeadmconstants.StaticPodAuditPolicyLogDir, kubeadmconstants.AuditPolicyLogFile)) + defaultArguments["audit-policy-file"] = kubeadmconstants.GetStaticPodAuditPolicyFile() + defaultArguments["audit-log-path"] = filepath.Join(kubeadmconstants.StaticPodAuditPolicyLogDir, kubeadmconstants.AuditPolicyLogFile) if cfg.AuditPolicyConfiguration.LogMaxAge == nil { - command = append(command, fmt.Sprintf("--audit-log-maxage=%d", kubeadmapiext.DefaultAuditPolicyLogMaxAge)) + defaultArguments["audit-log-maxage"] = fmt.Sprintf("%d", kubeadmapiext.DefaultAuditPolicyLogMaxAge) } else { - command = append(command, fmt.Sprintf("--audit-log-maxage=%d", *cfg.AuditPolicyConfiguration.LogMaxAge)) + defaultArguments["audit-log-maxage"] = fmt.Sprintf("%d", *cfg.AuditPolicyConfiguration.LogMaxAge) } } + command = append(command, kubeadmutil.BuildArgumentListFromMap(defaultArguments, cfg.APIServerExtraArgs)...) + command = append(command, getAuthzParameters(cfg.AuthorizationModes)...) + return command } diff --git a/cmd/kubeadm/app/phases/controlplane/manifests_test.go b/cmd/kubeadm/app/phases/controlplane/manifests_test.go index f9cabc68700..e36dc708acc 100644 --- a/cmd/kubeadm/app/phases/controlplane/manifests_test.go +++ b/cmd/kubeadm/app/phases/controlplane/manifests_test.go @@ -190,15 +190,16 @@ func TestCreatePrivilegedContainerForOpenStack(t *testing.T) { func TestGetAPIServerCommand(t *testing.T) { var tests = []struct { + name string cfg *kubeadmapi.MasterConfiguration expected []string }{ { + name: "testing defaults", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", @@ -231,48 +232,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "custom etcd cert and key files", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--secure-port=123", - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=1.2.3.4", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.1", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", @@ -305,55 +270,17 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ignores the audit policy if the feature gate is not enabled", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - "--enable-bootstrap-token-auth=true", - "--secure-port=123", - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=4.3.2.1", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.3", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, + CertificatesDir: testCertsDir, AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ Path: "/foo/bar", LogDir: "/foo/baz", LogMaxAge: utilpointer.Int32Ptr(10), - }, // ignored without the feature gate + }, }, expected: []string{ "kube-apiserver", @@ -386,12 +313,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ipv6 advertise address", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", @@ -424,51 +351,13 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "an external etcd with custom ca, certs and keys", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - FeatureGates: map[string]bool{features.HighAvailability: true}, - Etcd: kubeadmapi.Etcd{Endpoints: []string{"https://8.6.4.1:2379", "https://8.6.4.2:2379"}, CAFile: "fuz", CertFile: "fiz", KeyFile: "faz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + FeatureGates: map[string]bool{features.HighAvailability: true}, + Etcd: kubeadmapi.Etcd{Endpoints: []string{"https://8.6.4.1:2379", "https://8.6.4.2:2379"}, CAFile: "fuz", CertFile: "fiz", KeyFile: "faz"}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", @@ -502,12 +391,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "an insecure etcd", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{Endpoints: []string{"http://127.0.0.1:2379", "http://127.0.0.1:2380"}}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + Etcd: kubeadmapi.Etcd{Endpoints: []string{"http://127.0.0.1:2379", "http://127.0.0.1:2380"}}, + CertificatesDir: testCertsDir, }, expected: []string{ "kube-apiserver", @@ -537,50 +426,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "auditing and HA are enabled with a custom log max age of 0", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - Etcd: kubeadmapi.Etcd{CAFile: "fuz"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - }, - expected: []string{ - "kube-apiserver", - "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", - "--service-cluster-ip-range=bar", - "--service-account-key-file=" + testCertsDir + "/sa.pub", - "--client-ca-file=" + testCertsDir + "/ca.crt", - "--tls-cert-file=" + testCertsDir + "/apiserver.crt", - "--tls-private-key-file=" + testCertsDir + "/apiserver.key", - "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", - "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), - "--allow-privileged=true", - "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", - "--enable-bootstrap-token-auth=true", - "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", - "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", - "--requestheader-username-headers=X-Remote-User", - "--requestheader-group-headers=X-Remote-Group", - "--requestheader-extra-headers-prefix=X-Remote-Extra-", - "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", - "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=Node,RBAC", - "--advertise-address=2001:db8::1", - "--etcd-servers=https://127.0.0.1:2379", - "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", - "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", - "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", - }, - }, - { - cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - FeatureGates: map[string]bool{features.HighAvailability: true, features.Auditing: true}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "2001:db8::1"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + FeatureGates: map[string]bool{features.HighAvailability: true, features.Auditing: true}, + CertificatesDir: testCertsDir, AuditPolicyConfiguration: kubeadmapi.AuditPolicyConfiguration{ LogMaxAge: utilpointer.Int32Ptr(0), }, @@ -620,12 +471,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ensure gce cloud provider gets passed through", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - CloudProvider: "gce", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + CloudProvider: "gce", }, expected: []string{ "kube-apiserver", @@ -659,12 +510,12 @@ func TestGetAPIServerCommand(t *testing.T) { }, }, { + name: "ensure aws cloud provider gets passed through", cfg: &kubeadmapi.MasterConfiguration{ - API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, - Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.9.0-beta.0", - CloudProvider: "aws", + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + CloudProvider: "aws", }, expected: []string{ "kube-apiserver", @@ -697,15 +548,104 @@ func TestGetAPIServerCommand(t *testing.T) { "--cloud-provider=aws", }, }, + { + name: "ensure the DynamicKubelet flag gets passed through", + cfg: &kubeadmapi.MasterConfiguration{ + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + FeatureGates: map[string]bool{features.DynamicKubeletConfig: true}, + }, + expected: []string{ + "kube-apiserver", + "--insecure-port=0", + "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--service-cluster-ip-range=bar", + "--service-account-key-file=" + testCertsDir + "/sa.pub", + "--client-ca-file=" + testCertsDir + "/ca.crt", + "--tls-cert-file=" + testCertsDir + "/apiserver.crt", + "--tls-private-key-file=" + testCertsDir + "/apiserver.key", + "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", + "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", + "--enable-bootstrap-token-auth=true", + "--secure-port=123", + "--allow-privileged=true", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", + "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", + "--requestheader-username-headers=X-Remote-User", + "--requestheader-group-headers=X-Remote-Group", + "--requestheader-extra-headers-prefix=X-Remote-Extra-", + "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", + "--requestheader-allowed-names=front-proxy-client", + "--authorization-mode=Node,RBAC", + "--advertise-address=1.2.3.4", + "--etcd-servers=https://127.0.0.1:2379", + "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", + "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", + "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--feature-gates=DynamicKubeletConfig=true", + }, + }, + { + name: "test APIServerExtraArgs works as expected", + cfg: &kubeadmapi.MasterConfiguration{ + API: kubeadmapi.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, + Networking: kubeadmapi.Networking{ServiceSubnet: "bar"}, + CertificatesDir: testCertsDir, + FeatureGates: map[string]bool{features.DynamicKubeletConfig: true, features.Auditing: true}, + APIServerExtraArgs: map[string]string{ + "service-cluster-ip-range": "baz", + "advertise-address": "9.9.9.9", + "audit-policy-file": "/etc/config/audit.yaml", + "audit-log-path": "/var/log/kubernetes", + }, + }, + expected: []string{ + "kube-apiserver", + "--insecure-port=0", + "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota", + "--service-cluster-ip-range=baz", + "--service-account-key-file=" + testCertsDir + "/sa.pub", + "--client-ca-file=" + testCertsDir + "/ca.crt", + "--tls-cert-file=" + testCertsDir + "/apiserver.crt", + "--tls-private-key-file=" + testCertsDir + "/apiserver.key", + "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", + "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", + "--enable-bootstrap-token-auth=true", + "--secure-port=123", + "--allow-privileged=true", + "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", + "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", + "--requestheader-username-headers=X-Remote-User", + "--requestheader-group-headers=X-Remote-Group", + "--requestheader-extra-headers-prefix=X-Remote-Extra-", + "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", + "--requestheader-allowed-names=front-proxy-client", + "--authorization-mode=Node,RBAC", + "--advertise-address=9.9.9.9", + "--etcd-servers=https://127.0.0.1:2379", + "--etcd-cafile=" + testCertsDir + "/etcd/ca.crt", + "--etcd-certfile=" + testCertsDir + "/apiserver-etcd-client.crt", + "--etcd-keyfile=" + testCertsDir + "/apiserver-etcd-client.key", + "--feature-gates=DynamicKubeletConfig=true", + "--audit-policy-file=/etc/config/audit.yaml", + "--audit-log-path=/var/log/kubernetes", + "--audit-log-maxage=2", + }, + }, } for _, rt := range tests { - actual := getAPIServerCommand(rt.cfg, version.MustParseSemantic(rt.cfg.KubernetesVersion)) - sort.Strings(actual) - sort.Strings(rt.expected) - if !reflect.DeepEqual(actual, rt.expected) { - t.Errorf("failed getAPIServerCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) - } + t.Run(rt.name, func(t *testing.T) { + actual := getAPIServerCommand(rt.cfg) + sort.Strings(actual) + sort.Strings(rt.expected) + if !reflect.DeepEqual(actual, rt.expected) { + t.Errorf("failed getAPIServerCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual) + } + }) } }