mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
kubeadm: Adding unit tests for newly added funcs
This commit is contained in:
parent
d1acdf1627
commit
21eeb5c925
@ -18,10 +18,10 @@ package selfhosting
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
@ -72,9 +72,8 @@ func TestMutatePodSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
for _, rt := range tests {
|
||||
mutatePodSpec(cfg, rt.component, rt.podSpec)
|
||||
mutatePodSpec(getDefaultMutators(), rt.component, rt.podSpec)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed mutatePodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
@ -110,9 +109,8 @@ func TestAddNodeSelectorToPodSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
for _, rt := range tests {
|
||||
addNodeSelectorToPodSpec(cfg, rt.podSpec)
|
||||
addNodeSelectorToPodSpec(rt.podSpec)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
@ -148,9 +146,8 @@ func TestSetMasterTolerationOnPodSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
for _, rt := range tests {
|
||||
setMasterTolerationOnPodSpec(cfg, rt.podSpec)
|
||||
setMasterTolerationOnPodSpec(rt.podSpec)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
@ -179,12 +176,281 @@ func TestSetRightDNSPolicyOnPodSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.MasterConfiguration{}
|
||||
for _, rt := range tests {
|
||||
setRightDNSPolicyOnPodSpec(cfg, rt.podSpec)
|
||||
setRightDNSPolicyOnPodSpec(rt.podSpec)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSelfHostedVolumesForAPIServer(t *testing.T) {
|
||||
var tests = []struct {
|
||||
podSpec *v1.PodSpec
|
||||
expected v1.PodSpec
|
||||
}{
|
||||
{
|
||||
podSpec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
MountPath: "/etc/kubernetes/pki",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/ssl/certs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/kubernetes/pki",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
MountPath: "/etc/kubernetes/pki",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/ssl/certs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
VolumeSource: apiServerCertificatesVolumeSource(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
setSelfHostedVolumesForAPIServer(rt.podSpec)
|
||||
sort.Strings(rt.podSpec.Containers[0].Command)
|
||||
sort.Strings(rt.expected.Containers[0].Command)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed setSelfHostedVolumesForAPIServer:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSelfHostedVolumesForControllerManager(t *testing.T) {
|
||||
var tests = []struct {
|
||||
podSpec *v1.PodSpec
|
||||
expected v1.PodSpec
|
||||
}{
|
||||
{
|
||||
podSpec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
MountPath: "/etc/kubernetes/pki",
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
MountPath: "/etc/kubernetes/controller-manager.conf",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--kubeconfig=/etc/kubernetes/controller-manager.conf",
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/ssl/certs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/kubernetes/pki",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/kubernetes/controller-manager.conf",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
MountPath: "/etc/ssl/certs",
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
MountPath: "/etc/kubernetes/pki",
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
MountPath: "/etc/kubernetes/kubeconfig",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig/controller-manager.conf",
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "ca-certs",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/ssl/certs",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "k8s-certs",
|
||||
VolumeSource: controllerManagerCertificatesVolumeSource(),
|
||||
},
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: kubeConfigVolumeSource(kubeadmconstants.ControllerManagerKubeConfigFileName),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
setSelfHostedVolumesForControllerManager(rt.podSpec)
|
||||
sort.Strings(rt.podSpec.Containers[0].Command)
|
||||
sort.Strings(rt.expected.Containers[0].Command)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed setSelfHostedVolumesForControllerManager:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSelfHostedVolumesForScheduler(t *testing.T) {
|
||||
var tests = []struct {
|
||||
podSpec *v1.PodSpec
|
||||
expected v1.PodSpec
|
||||
}{
|
||||
{
|
||||
podSpec: &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
MountPath: "/etc/kubernetes/scheduler.conf",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--kubeconfig=/etc/kubernetes/scheduler.conf",
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/etc/kubernetes/scheduler.conf",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
MountPath: "/etc/kubernetes/kubeconfig",
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig/scheduler.conf",
|
||||
"--foo=bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []v1.Volume{
|
||||
{
|
||||
Name: "kubeconfig",
|
||||
VolumeSource: kubeConfigVolumeSource(kubeadmconstants.SchedulerKubeConfigFileName),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
setSelfHostedVolumesForScheduler(rt.podSpec)
|
||||
sort.Strings(rt.podSpec.Containers[0].Command)
|
||||
sort.Strings(rt.expected.Containers[0].Command)
|
||||
|
||||
if !reflect.DeepEqual(*rt.podSpec, rt.expected) {
|
||||
t.Errorf("failed setSelfHostedVolumesForScheduler:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,88 +21,13 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/cmd/features"
|
||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
apiProjectedSecret = `- name: k8s
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: ca.crt
|
||||
- key: tls.key
|
||||
path: ca.key
|
||||
name: ca
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: apiserver.crt
|
||||
- key: tls.key
|
||||
path: apiserver.key
|
||||
name: apiserver
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: apiserver-kubelet-client.crt
|
||||
- key: tls.key
|
||||
path: apiserver-kubelet-client.key
|
||||
name: apiserver-kubelet-client
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: sa.pub
|
||||
- key: tls.key
|
||||
path: sa.key
|
||||
name: sa
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: front-proxy-ca.crt
|
||||
name: front-proxy-ca
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: front-proxy-client.crt
|
||||
- key: tls.key
|
||||
path: front-proxy-client.key
|
||||
name: front-proxy-client`
|
||||
|
||||
controllerManagerProjectedSecret = `- name: k8s
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
name: controller-manager.conf
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.crt
|
||||
path: ca.crt
|
||||
- key: tls.key
|
||||
path: ca.key
|
||||
name: ca
|
||||
- secret:
|
||||
items:
|
||||
- key: tls.key
|
||||
path: sa.key
|
||||
name: sa`
|
||||
|
||||
schedulerProjectedSecret = `- name: k8s
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
name: scheduler.conf`
|
||||
|
||||
hostPathVol = `- hostPath:
|
||||
path: /etc/kubernetes
|
||||
name: k8s`
|
||||
|
||||
testAPIServerPod = `
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
@ -110,39 +35,36 @@ metadata:
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
component: kube-apiserver
|
||||
tier: control-plane
|
||||
name: kube-apiserver
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-apiserver
|
||||
- --client-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
|
||||
- --allow-privileged=true
|
||||
- --service-cluster-ip-range=10.96.0.0/12
|
||||
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
|
||||
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
|
||||
- --secure-port=6443
|
||||
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||
- --requestheader-group-headers=X-Remote-Group
|
||||
- --service-cluster-ip-range=10.96.0.0/12
|
||||
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
|
||||
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
|
||||
- --secure-port=6443
|
||||
- --insecure-port=0
|
||||
- --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota
|
||||
- --requestheader-extra-headers-prefix=X-Remote-Extra-
|
||||
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
|
||||
- --experimental-bootstrap-token-auth=true
|
||||
- --requestheader-group-headers=X-Remote-Group
|
||||
- --requestheader-allowed-names=front-proxy-client
|
||||
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
|
||||
- --advertise-address=192.168.1.115
|
||||
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
|
||||
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||
- --insecure-port=0
|
||||
- --experimental-bootstrap-token-auth=true
|
||||
- --requestheader-username-headers=X-Remote-User
|
||||
- --requestheader-extra-headers-prefix=X-Remote-Extra-
|
||||
- --requestheader-allowed-names=front-proxy-client
|
||||
- --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota
|
||||
- --allow-privileged=true
|
||||
- --client-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
|
||||
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
|
||||
- --authorization-mode=Node,RBAC
|
||||
- --advertise-address=192.168.200.101
|
||||
- --etcd-servers=http://127.0.0.1:2379
|
||||
image: gcr.io/google_containers/kube-apiserver-amd64:v1.7.0
|
||||
image: gcr.io/google_containers/kube-apiserver-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -157,22 +79,26 @@ spec:
|
||||
requests:
|
||||
cpu: 250m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
- hostPath:
|
||||
path: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
status: {}
|
||||
`
|
||||
|
||||
@ -192,30 +118,30 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-apiserver
|
||||
- --client-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
|
||||
- --allow-privileged=true
|
||||
- --service-cluster-ip-range=10.96.0.0/12
|
||||
- --service-account-key-file=/etc/kubernetes/pki/sa.pub
|
||||
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
|
||||
- --secure-port=6443
|
||||
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||
- --requestheader-group-headers=X-Remote-Group
|
||||
- --service-cluster-ip-range=10.96.0.0/12
|
||||
- --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
|
||||
- --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
|
||||
- --secure-port=6443
|
||||
- --insecure-port=0
|
||||
- --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota
|
||||
- --requestheader-extra-headers-prefix=X-Remote-Extra-
|
||||
- --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
|
||||
- --experimental-bootstrap-token-auth=true
|
||||
- --requestheader-group-headers=X-Remote-Group
|
||||
- --requestheader-allowed-names=front-proxy-client
|
||||
- --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
|
||||
- --advertise-address=192.168.1.115
|
||||
- --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
|
||||
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||
- --insecure-port=0
|
||||
- --experimental-bootstrap-token-auth=true
|
||||
- --requestheader-username-headers=X-Remote-User
|
||||
- --requestheader-extra-headers-prefix=X-Remote-Extra-
|
||||
- --requestheader-allowed-names=front-proxy-client
|
||||
- --admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota
|
||||
- --allow-privileged=true
|
||||
- --client-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
|
||||
- --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
|
||||
- --authorization-mode=Node,RBAC
|
||||
- --advertise-address=192.168.200.101
|
||||
- --etcd-servers=http://127.0.0.1:2379
|
||||
image: gcr.io/google_containers/kube-apiserver-amd64:v1.7.0
|
||||
image: gcr.io/google_containers/kube-apiserver-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -230,13 +156,15 @@ spec:
|
||||
requests:
|
||||
cpu: 250m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
readOnly: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
nodeSelector:
|
||||
@ -245,13 +173,15 @@ spec:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
- hostPath:
|
||||
path: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
updateStrategy: {}
|
||||
status:
|
||||
currentNumberScheduled: 0
|
||||
@ -267,25 +197,22 @@ metadata:
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
component: kube-controller-manager
|
||||
tier: control-plane
|
||||
name: kube-controller-manager
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-controller-manager
|
||||
- --leader-elect=true
|
||||
- --controllers=*,bootstrapsigner,tokencleaner
|
||||
- --kubeconfig=/etc/kubernetes/controller-manager.conf
|
||||
- --root-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --service-account-private-key-file=/etc/kubernetes/pki/sa.key
|
||||
- --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
|
||||
- --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
|
||||
- --leader-elect=true
|
||||
- --kubeconfig=/etc/kubernetes/controller-manager.conf
|
||||
- --controllers=*,bootstrapsigner,tokencleaner
|
||||
- --root-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --address=127.0.0.1
|
||||
- --use-service-account-credentials=true
|
||||
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.7.0
|
||||
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -300,22 +227,32 @@ spec:
|
||||
requests:
|
||||
cpu: 200m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/kubernetes/controller-manager.conf
|
||||
name: kubeconfig
|
||||
readOnly: true
|
||||
- mountPath: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/controller-manager.conf
|
||||
name: kubeconfig
|
||||
- hostPath:
|
||||
path: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
status: {}
|
||||
`
|
||||
|
||||
@ -335,16 +272,16 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-controller-manager
|
||||
- --leader-elect=true
|
||||
- --controllers=*,bootstrapsigner,tokencleaner
|
||||
- --kubeconfig=/etc/kubernetes/controller-manager.conf
|
||||
- --root-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --service-account-private-key-file=/etc/kubernetes/pki/sa.key
|
||||
- --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
|
||||
- --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
|
||||
- --leader-elect=true
|
||||
- --kubeconfig=/etc/kubernetes/controller-manager.conf
|
||||
- --controllers=*,bootstrapsigner,tokencleaner
|
||||
- --root-ca-file=/etc/kubernetes/pki/ca.crt
|
||||
- --address=127.0.0.1
|
||||
- --use-service-account-credentials=true
|
||||
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.7.0
|
||||
image: gcr.io/google_containers/kube-controller-manager-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -359,13 +296,18 @@ spec:
|
||||
requests:
|
||||
cpu: 200m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
readOnly: true
|
||||
- mountPath: /etc/kubernetes/controller-manager.conf
|
||||
name: kubeconfig
|
||||
readOnly: true
|
||||
- mountPath: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
readOnly: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
nodeSelector:
|
||||
@ -374,13 +316,18 @@ spec:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/pki
|
||||
name: k8s-certs
|
||||
- hostPath:
|
||||
path: /etc/ssl/certs
|
||||
name: certs
|
||||
name: ca-certs
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/controller-manager.conf
|
||||
name: kubeconfig
|
||||
- hostPath:
|
||||
path: /etc/pki
|
||||
name: pki
|
||||
name: ca-certs-etc-pki
|
||||
updateStrategy: {}
|
||||
status:
|
||||
currentNumberScheduled: 0
|
||||
@ -396,19 +343,16 @@ metadata:
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
component: kube-scheduler
|
||||
tier: control-plane
|
||||
name: kube-scheduler
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-scheduler
|
||||
- --address=127.0.0.1
|
||||
- --leader-elect=true
|
||||
- --kubeconfig=/etc/kubernetes/scheduler.conf
|
||||
image: gcr.io/google_containers/kube-scheduler-amd64:v1.7.0
|
||||
- --address=127.0.0.1
|
||||
image: gcr.io/google_containers/kube-scheduler-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -423,12 +367,14 @@ spec:
|
||||
requests:
|
||||
cpu: 100m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/scheduler.conf
|
||||
name: kubeconfig
|
||||
readOnly: true
|
||||
hostNetwork: true
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/scheduler.conf
|
||||
name: kubeconfig
|
||||
status: {}
|
||||
`
|
||||
|
||||
@ -448,10 +394,10 @@ spec:
|
||||
containers:
|
||||
- command:
|
||||
- kube-scheduler
|
||||
- --address=127.0.0.1
|
||||
- --leader-elect=true
|
||||
- --kubeconfig=/etc/kubernetes/scheduler.conf
|
||||
image: gcr.io/google_containers/kube-scheduler-amd64:v1.7.0
|
||||
- --address=127.0.0.1
|
||||
image: gcr.io/google_containers/kube-scheduler-amd64:v1.7.4
|
||||
livenessProbe:
|
||||
failureThreshold: 8
|
||||
httpGet:
|
||||
@ -466,8 +412,8 @@ spec:
|
||||
requests:
|
||||
cpu: 100m
|
||||
volumeMounts:
|
||||
- mountPath: /etc/kubernetes
|
||||
name: k8s
|
||||
- mountPath: /etc/kubernetes/scheduler.conf
|
||||
name: kubeconfig
|
||||
readOnly: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostNetwork: true
|
||||
@ -477,7 +423,9 @@ spec:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
volumes:
|
||||
%s
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/scheduler.conf
|
||||
name: kubeconfig
|
||||
updateStrategy: {}
|
||||
status:
|
||||
currentNumberScheduled: 0
|
||||
@ -487,67 +435,26 @@ status:
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
testAPIServerSecretsPod = fmt.Sprintf(testAPIServerPod, apiProjectedSecret)
|
||||
testAPIServerSecretsDS = fmt.Sprintf(testAPIServerDaemonSet, indentString(apiProjectedSecret, 4))
|
||||
testAPIServerHostPathPod = fmt.Sprintf(testAPIServerPod, hostPathVol)
|
||||
testAPIServerHostPathDS = fmt.Sprintf(testAPIServerDaemonSet, indentString(hostPathVol, 4))
|
||||
|
||||
testSchedulerSecretsPod = fmt.Sprintf(testSchedulerPod, schedulerProjectedSecret)
|
||||
testSchedulerSecretsDS = fmt.Sprintf(testSchedulerDaemonSet, indentString(schedulerProjectedSecret, 4))
|
||||
testSchedulerHostPathPod = fmt.Sprintf(testSchedulerPod, hostPathVol)
|
||||
testSchedulerHostPathDS = fmt.Sprintf(testSchedulerDaemonSet, indentString(hostPathVol, 4))
|
||||
|
||||
testControllerManagerSecretsPod = fmt.Sprintf(testControllerManagerPod, controllerManagerProjectedSecret)
|
||||
testControllerManagerSecretsDS = fmt.Sprintf(testControllerManagerDaemonSet, indentString(controllerManagerProjectedSecret, 4))
|
||||
testControllerManagerHostPathPod = fmt.Sprintf(testControllerManagerPod, hostPathVol)
|
||||
testControllerManagerHostPathDS = fmt.Sprintf(testControllerManagerDaemonSet, indentString(hostPathVol, 4))
|
||||
)
|
||||
|
||||
func TestBuildDaemonSet(t *testing.T) {
|
||||
var tests = []struct {
|
||||
component string
|
||||
podBytes []byte
|
||||
dsBytes []byte
|
||||
selfHostedSecrets bool
|
||||
component string
|
||||
podBytes []byte
|
||||
dsBytes []byte
|
||||
}{
|
||||
// vols as secrets
|
||||
{
|
||||
component: kubeadmconstants.KubeAPIServer,
|
||||
podBytes: []byte(testAPIServerSecretsPod),
|
||||
dsBytes: []byte(testAPIServerSecretsDS),
|
||||
selfHostedSecrets: true,
|
||||
component: constants.KubeAPIServer,
|
||||
podBytes: []byte(testAPIServerPod),
|
||||
dsBytes: []byte(testAPIServerDaemonSet),
|
||||
},
|
||||
{
|
||||
component: kubeadmconstants.KubeControllerManager,
|
||||
podBytes: []byte(testControllerManagerSecretsPod),
|
||||
dsBytes: []byte(testControllerManagerSecretsDS),
|
||||
selfHostedSecrets: true,
|
||||
component: constants.KubeControllerManager,
|
||||
podBytes: []byte(testControllerManagerPod),
|
||||
dsBytes: []byte(testControllerManagerDaemonSet),
|
||||
},
|
||||
{
|
||||
component: kubeadmconstants.KubeScheduler,
|
||||
podBytes: []byte(testSchedulerSecretsPod),
|
||||
dsBytes: []byte(testSchedulerSecretsDS),
|
||||
selfHostedSecrets: true,
|
||||
},
|
||||
// hostPath vols
|
||||
{
|
||||
component: kubeadmconstants.KubeAPIServer,
|
||||
podBytes: []byte(testAPIServerHostPathPod),
|
||||
dsBytes: []byte(testAPIServerHostPathDS),
|
||||
selfHostedSecrets: false,
|
||||
},
|
||||
{
|
||||
component: kubeadmconstants.KubeControllerManager,
|
||||
podBytes: []byte(testControllerManagerHostPathPod),
|
||||
dsBytes: []byte(testControllerManagerHostPathDS),
|
||||
selfHostedSecrets: false,
|
||||
},
|
||||
{
|
||||
component: kubeadmconstants.KubeScheduler,
|
||||
podBytes: []byte(testSchedulerHostPathPod),
|
||||
dsBytes: []byte(testSchedulerHostPathDS),
|
||||
selfHostedSecrets: false,
|
||||
component: constants.KubeScheduler,
|
||||
podBytes: []byte(testSchedulerPod),
|
||||
dsBytes: []byte(testSchedulerDaemonSet),
|
||||
},
|
||||
}
|
||||
|
||||
@ -557,21 +464,17 @@ func TestBuildDaemonSet(t *testing.T) {
|
||||
|
||||
podSpec, err := loadPodSpecFromFile(tempFile)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't load the specified Pod: %v", err)
|
||||
t.Fatalf("couldn't load the specified Pod")
|
||||
}
|
||||
|
||||
cfg := &kubeadmapi.MasterConfiguration{
|
||||
FeatureFlags: map[string]bool{string(features.StoreCertsInSecrets): rt.selfHostedSecrets},
|
||||
}
|
||||
|
||||
ds := buildDaemonSet(cfg, rt.component, podSpec)
|
||||
ds := buildDaemonSet(rt.component, podSpec, getDefaultMutators())
|
||||
dsBytes, err := yaml.Marshal(ds)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal daemonset to YAML: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(dsBytes, rt.dsBytes) {
|
||||
t.Errorf("failed TestBuildDaemonSet for name=%s (secrets=%t):\nexpected:\n%s\nsaw:\n%s", rt.component, rt.selfHostedSecrets, rt.dsBytes, dsBytes)
|
||||
t.Errorf("failed TestBuildDaemonSet:\nexpected:\n%s\nsaw:\n%s", rt.dsBytes, dsBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -651,18 +554,3 @@ func createTempFileWithContent(content []byte) (string, error) {
|
||||
}
|
||||
return tempFile.Name(), nil
|
||||
}
|
||||
|
||||
func indentString(input string, count int) string {
|
||||
output := ""
|
||||
lines := strings.Split(input, "\n")
|
||||
for i, line := range lines {
|
||||
if i > 0 {
|
||||
output += strings.Repeat(" ", count)
|
||||
}
|
||||
output += line
|
||||
if i < len(lines)-1 {
|
||||
output += "\n"
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
341
cmd/kubeadm/app/util/arguments_test.go
Normal file
341
cmd/kubeadm/app/util/arguments_test.go
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBuildArgumentListFromMap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
base map[string]string
|
||||
overrides map[string]string
|
||||
expected []string
|
||||
}{
|
||||
{ // override an argument from the base
|
||||
base: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle",
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
},
|
||||
overrides: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
},
|
||||
expected: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
},
|
||||
{ // add an argument that is not in base
|
||||
base: map[string]string{
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
},
|
||||
overrides: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
},
|
||||
expected: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
},
|
||||
{ // allow empty strings in base
|
||||
base: map[string]string{
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
"something-that-allows-empty-string": "",
|
||||
},
|
||||
overrides: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
},
|
||||
expected: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--something-that-allows-empty-string=",
|
||||
},
|
||||
},
|
||||
{ // allow empty strings in overrides
|
||||
base: map[string]string{
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
"something-that-allows-empty-string": "foo",
|
||||
},
|
||||
overrides: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
"something-that-allows-empty-string": "",
|
||||
},
|
||||
expected: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--something-that-allows-empty-string=",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actual := BuildArgumentListFromMap(rt.base, rt.overrides)
|
||||
sort.Strings(actual)
|
||||
sort.Strings(rt.expected)
|
||||
if !reflect.DeepEqual(actual, rt.expected) {
|
||||
t.Errorf("failed BuildArgumentListFromMap:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseArgumentListToMap(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args []string
|
||||
expectedMap map[string]string
|
||||
}{
|
||||
{
|
||||
// normal case
|
||||
args: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
expectedMap: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
},
|
||||
},
|
||||
{
|
||||
// test that feature-gates is working
|
||||
args: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--feature-gates=EnableFoo=true,EnableBar=false",
|
||||
},
|
||||
expectedMap: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
"feature-gates": "EnableFoo=true,EnableBar=false",
|
||||
},
|
||||
},
|
||||
{
|
||||
// test that a binary can be the first arg
|
||||
args: []string{
|
||||
"kube-apiserver",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--feature-gates=EnableFoo=true,EnableBar=false",
|
||||
},
|
||||
expectedMap: map[string]string{
|
||||
"admission-control": "NamespaceLifecycle,LimitRanger",
|
||||
"insecure-bind-address": "127.0.0.1",
|
||||
"allow-privileged": "true",
|
||||
"feature-gates": "EnableFoo=true,EnableBar=false",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actualMap := ParseArgumentListToMap(rt.args)
|
||||
if !reflect.DeepEqual(actualMap, rt.expectedMap) {
|
||||
t.Errorf("failed ParseArgumentListToMap:\nexpected:\n%v\nsaw:\n%v", rt.expectedMap, actualMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReplaceArgument(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args []string
|
||||
mutateFunc func(map[string]string) map[string]string
|
||||
expectedArgs []string
|
||||
}{
|
||||
{
|
||||
// normal case
|
||||
args: []string{
|
||||
"kube-apiserver",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
mutateFunc: func(argMap map[string]string) map[string]string {
|
||||
argMap["admission-control"] = "NamespaceLifecycle,LimitRanger,ResourceQuota"
|
||||
return argMap
|
||||
},
|
||||
expectedArgs: []string{
|
||||
"kube-apiserver",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger,ResourceQuota",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
},
|
||||
{
|
||||
// normal case
|
||||
args: []string{
|
||||
"kube-apiserver",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
mutateFunc: func(argMap map[string]string) map[string]string {
|
||||
argMap["new-arg-here"] = "foo"
|
||||
return argMap
|
||||
},
|
||||
expectedArgs: []string{
|
||||
"kube-apiserver",
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--new-arg-here=foo",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
actualArgs := ReplaceArgument(rt.args, rt.mutateFunc)
|
||||
sort.Strings(actualArgs)
|
||||
sort.Strings(rt.expectedArgs)
|
||||
if !reflect.DeepEqual(actualArgs, rt.expectedArgs) {
|
||||
t.Errorf("failed ReplaceArgument:\nexpected:\n%v\nsaw:\n%v", rt.expectedArgs, actualArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundtrip(t *testing.T) {
|
||||
var tests = []struct {
|
||||
args []string
|
||||
}{
|
||||
{
|
||||
// normal case
|
||||
args: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
},
|
||||
},
|
||||
{
|
||||
// test that feature-gates is working
|
||||
args: []string{
|
||||
"--admission-control=NamespaceLifecycle,LimitRanger",
|
||||
"--insecure-bind-address=127.0.0.1",
|
||||
"--allow-privileged=true",
|
||||
"--feature-gates=EnableFoo=true,EnableBar=false",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
// These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back
|
||||
actual := BuildArgumentListFromMap(ParseArgumentListToMap(rt.args), map[string]string{})
|
||||
sort.Strings(actual)
|
||||
sort.Strings(rt.args)
|
||||
|
||||
if !reflect.DeepEqual(actual, rt.args) {
|
||||
t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseArgument(t *testing.T) {
|
||||
var tests = []struct {
|
||||
arg string
|
||||
expectedKey string
|
||||
expectedVal string
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
// cannot be empty
|
||||
arg: "",
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
// must contain -- and =
|
||||
arg: "a",
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
// must contain -- and =
|
||||
arg: "a-z",
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
// must contain --
|
||||
arg: "a=b",
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
// must contain a key
|
||||
arg: "--=b",
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
// can contain key but no value
|
||||
arg: "--a=",
|
||||
expectedKey: "a",
|
||||
expectedVal: "",
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
// simple case
|
||||
arg: "--a=b",
|
||||
expectedKey: "a",
|
||||
expectedVal: "b",
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
// keys/values with '-' should be supported
|
||||
arg: "--very-long-flag-name=some-value",
|
||||
expectedKey: "very-long-flag-name",
|
||||
expectedVal: "some-value",
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
// numbers should be handled correctly
|
||||
arg: "--some-number=0.2",
|
||||
expectedKey: "some-number",
|
||||
expectedVal: "0.2",
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
// lists should be handled correctly
|
||||
arg: "--admission-control=foo,bar,baz",
|
||||
expectedKey: "admission-control",
|
||||
expectedVal: "foo,bar,baz",
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
// more than one '=' should be allowed
|
||||
arg: "--feature-gates=EnableFoo=true,EnableBar=false",
|
||||
expectedKey: "feature-gates",
|
||||
expectedVal: "EnableFoo=true,EnableBar=false",
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, rt := range tests {
|
||||
key, val, actual := parseArgument(rt.arg)
|
||||
if (actual != nil) != rt.expectedErr {
|
||||
t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual)
|
||||
}
|
||||
if (key != rt.expectedKey) || (val != rt.expectedVal) {
|
||||
t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user