From 9f1c5a6f0f86651b651a07d57dfba6a6779d4eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Thu, 6 Jul 2017 20:54:47 +0300 Subject: [PATCH] kubeadm self-hosting: unit tests and bazel --- cmd/kubeadm/app/BUILD | 1 + cmd/kubeadm/app/cmd/BUILD | 1 + cmd/kubeadm/app/cmd/phases/BUILD | 3 + cmd/kubeadm/app/phases/controlplane/BUILD | 9 +- cmd/kubeadm/app/phases/selfhosting/BUILD | 57 ++ .../selfhosting/podspec_mutation_test.go | 185 ++++++ .../phases/selfhosting/selfhosting_test.go | 544 ++++++++++++++++++ cmd/kubeadm/app/util/BUILD | 2 + hack/.linted_packages | 2 + 9 files changed, 796 insertions(+), 8 deletions(-) create mode 100644 cmd/kubeadm/app/phases/selfhosting/BUILD create mode 100644 cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go create mode 100644 cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go diff --git a/cmd/kubeadm/app/BUILD b/cmd/kubeadm/app/BUILD index dde909a1262..457e8b42e37 100644 --- a/cmd/kubeadm/app/BUILD +++ b/cmd/kubeadm/app/BUILD @@ -41,6 +41,7 @@ filegroup( "//cmd/kubeadm/app/phases/certs:all-srcs", "//cmd/kubeadm/app/phases/controlplane:all-srcs", "//cmd/kubeadm/app/phases/kubeconfig:all-srcs", + "//cmd/kubeadm/app/phases/selfhosting:all-srcs", "//cmd/kubeadm/app/phases/token:all-srcs", "//cmd/kubeadm/app/preflight:all-srcs", "//cmd/kubeadm/app/util:all-srcs", diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index 544a68d6f36..a120c6ae7cd 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -34,6 +34,7 @@ go_library( "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/phases/controlplane:go_default_library", "//cmd/kubeadm/app/phases/kubeconfig:go_default_library", + "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/phases/token:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", diff --git a/cmd/kubeadm/app/cmd/phases/BUILD b/cmd/kubeadm/app/cmd/phases/BUILD index 883f2c40f2a..98fddf940bf 100644 --- a/cmd/kubeadm/app/cmd/phases/BUILD +++ b/cmd/kubeadm/app/cmd/phases/BUILD @@ -14,6 +14,7 @@ go_library( "kubeconfig.go", "phase.go", "preflight.go", + "selfhosting.go", ], tags = ["automanaged"], deps = [ @@ -22,8 +23,10 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library", "//cmd/kubeadm/app/phases/certs:go_default_library", "//cmd/kubeadm/app/phases/kubeconfig:go_default_library", + "//cmd/kubeadm/app/phases/selfhosting:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util:go_default_library", + "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//pkg/api:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", diff --git a/cmd/kubeadm/app/phases/controlplane/BUILD b/cmd/kubeadm/app/phases/controlplane/BUILD index 1676ac07402..83ef59764a3 100644 --- a/cmd/kubeadm/app/phases/controlplane/BUILD +++ b/cmd/kubeadm/app/phases/controlplane/BUILD @@ -25,30 +25,23 @@ go_test( go_library( name = "go_default_library", - srcs = [ - "manifests.go", - "selfhosted.go", - ], + srcs = ["manifests.go"], tags = ["automanaged"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/images:go_default_library", - "//cmd/kubeadm/app/util:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/util/version:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", ], ) diff --git a/cmd/kubeadm/app/phases/selfhosting/BUILD b/cmd/kubeadm/app/phases/selfhosting/BUILD new file mode 100644 index 00000000000..913e88bfcbd --- /dev/null +++ b/cmd/kubeadm/app/phases/selfhosting/BUILD @@ -0,0 +1,57 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = [ + "podspec_mutation_test.go", + "selfhosting_test.go", + ], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//cmd/kubeadm/app/constants:go_default_library", + "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + ], +) + +go_library( + name = "go_default_library", + srcs = [ + "podspec_mutation.go", + "selfhosting.go", + ], + tags = ["automanaged"], + deps = [ + "//cmd/kubeadm/app/constants:go_default_library", + "//cmd/kubeadm/app/util:go_default_library", + "//pkg/api:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go new file mode 100644 index 00000000000..beb90d8aa08 --- /dev/null +++ b/cmd/kubeadm/app/phases/selfhosting/podspec_mutation_test.go @@ -0,0 +1,185 @@ +/* +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 selfhosting + +import ( + "reflect" + "testing" + + "k8s.io/api/core/v1" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" +) + +func TestMutatePodSpec(t *testing.T) { + var tests = []struct { + component string + podSpec *v1.PodSpec + expected v1.PodSpec + }{ + { + component: kubeAPIServer, + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + NodeSelector: map[string]string{ + kubeadmconstants.LabelNodeRoleMaster: "", + }, + Tolerations: []v1.Toleration{ + kubeadmconstants.MasterToleration, + }, + DNSPolicy: v1.DNSClusterFirstWithHostNet, + }, + }, + { + component: kubeControllerManager, + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + NodeSelector: map[string]string{ + kubeadmconstants.LabelNodeRoleMaster: "", + }, + Tolerations: []v1.Toleration{ + kubeadmconstants.MasterToleration, + }, + DNSPolicy: v1.DNSClusterFirstWithHostNet, + }, + }, + { + component: kubeScheduler, + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + NodeSelector: map[string]string{ + kubeadmconstants.LabelNodeRoleMaster: "", + }, + Tolerations: []v1.Toleration{ + kubeadmconstants.MasterToleration, + }, + DNSPolicy: v1.DNSClusterFirstWithHostNet, + }, + }, + } + + for _, rt := range tests { + mutatePodSpec(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) + } + } +} + +func TestAddNodeSelectorToPodSpec(t *testing.T) { + var tests = []struct { + podSpec *v1.PodSpec + expected v1.PodSpec + }{ + { + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + NodeSelector: map[string]string{ + kubeadmconstants.LabelNodeRoleMaster: "", + }, + }, + }, + { + podSpec: &v1.PodSpec{ + NodeSelector: map[string]string{ + "foo": "bar", + }, + }, + expected: v1.PodSpec{ + NodeSelector: map[string]string{ + "foo": "bar", + kubeadmconstants.LabelNodeRoleMaster: "", + }, + }, + }, + } + + for _, rt := range tests { + addNodeSelectorToPodSpec(rt.podSpec) + + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed addNodeSelectorToPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + } +} + +func TestSetMasterTolerationOnPodSpec(t *testing.T) { + var tests = []struct { + podSpec *v1.PodSpec + expected v1.PodSpec + }{ + { + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + Tolerations: []v1.Toleration{ + kubeadmconstants.MasterToleration, + }, + }, + }, + { + podSpec: &v1.PodSpec{ + Tolerations: []v1.Toleration{ + {Key: "foo", Value: "bar"}, + }, + }, + expected: v1.PodSpec{ + Tolerations: []v1.Toleration{ + {Key: "foo", Value: "bar"}, + kubeadmconstants.MasterToleration, + }, + }, + }, + } + + for _, rt := range tests { + setMasterTolerationOnPodSpec(rt.podSpec) + + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setMasterTolerationOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + } +} + +func TestSetRightDNSPolicyOnPodSpec(t *testing.T) { + var tests = []struct { + podSpec *v1.PodSpec + expected v1.PodSpec + }{ + { + podSpec: &v1.PodSpec{}, + expected: v1.PodSpec{ + DNSPolicy: v1.DNSClusterFirstWithHostNet, + }, + }, + { + podSpec: &v1.PodSpec{ + DNSPolicy: v1.DNSClusterFirst, + }, + expected: v1.PodSpec{ + DNSPolicy: v1.DNSClusterFirstWithHostNet, + }, + }, + } + + for _, rt := range tests { + setRightDNSPolicyOnPodSpec(rt.podSpec) + + if !reflect.DeepEqual(*rt.podSpec, rt.expected) { + t.Errorf("failed setRightDNSPolicyOnPodSpec:\nexpected:\n%v\nsaw:\n%v", rt.expected, *rt.podSpec) + } + } +} diff --git a/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go new file mode 100644 index 00000000000..11b2ce791ff --- /dev/null +++ b/cmd/kubeadm/app/phases/selfhosting/selfhosting_test.go @@ -0,0 +1,544 @@ +/* +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 selfhosting + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/ghodss/yaml" +) + +const ( + testAPIServerPod = ` +apiVersion: v1 +kind: Pod +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 + - --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 + - --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 + - --requestheader-username-headers=X-Remote-User + - --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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 6443 + scheme: HTTPS + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-apiserver + resources: + requests: + cpu: 250m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + - mountPath: /etc/ssl/certs + name: certs + - mountPath: /etc/pki + name: pki + hostNetwork: true + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s + - hostPath: + path: /etc/ssl/certs + name: certs + - hostPath: + path: /etc/pki + name: pki +status: {} +` + + testAPIServerDaemonSet = `metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-apiserver + name: self-hosted-kube-apiserver + namespace: kube-system +spec: + template: + metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-apiserver + 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 + - --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 + - --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 + - --requestheader-username-headers=X-Remote-User + - --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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 6443 + scheme: HTTPS + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-apiserver + resources: + requests: + cpu: 250m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + - mountPath: /etc/ssl/certs + name: certs + - mountPath: /etc/pki + name: pki + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/master: "" + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s + - hostPath: + path: /etc/ssl/certs + name: certs + - hostPath: + path: /etc/pki + name: pki + updateStrategy: {} +status: + currentNumberScheduled: 0 + desiredNumberScheduled: 0 + numberMisscheduled: 0 + numberReady: 0 +` + + testControllerManagerPod = ` +apiVersion: v1 +kind: Pod +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 + - --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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10252 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-controller-manager + resources: + requests: + cpu: 200m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + - mountPath: /etc/ssl/certs + name: certs + - mountPath: /etc/pki + name: pki + hostNetwork: true + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s + - hostPath: + path: /etc/ssl/certs + name: certs + - hostPath: + path: /etc/pki + name: pki +status: {} +` + + testControllerManagerDaemonSet = `metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-controller-manager + name: self-hosted-kube-controller-manager + namespace: kube-system +spec: + template: + metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-controller-manager + spec: + containers: + - command: + - kube-controller-manager + - --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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10252 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-controller-manager + resources: + requests: + cpu: 200m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + - mountPath: /etc/ssl/certs + name: certs + - mountPath: /etc/pki + name: pki + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/master: "" + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s + - hostPath: + path: /etc/ssl/certs + name: certs + - hostPath: + path: /etc/pki + name: pki + updateStrategy: {} +status: + currentNumberScheduled: 0 + desiredNumberScheduled: 0 + numberMisscheduled: 0 + numberReady: 0 +` + + testSchedulerPod = ` +apiVersion: v1 +kind: Pod +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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10251 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-scheduler + resources: + requests: + cpu: 100m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + hostNetwork: true + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s +status: {} +` + + testSchedulerDaemonSet = `metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-scheduler + name: self-hosted-kube-scheduler + namespace: kube-system +spec: + template: + metadata: + creationTimestamp: null + labels: + k8s-app: self-hosted-kube-scheduler + 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 + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10251 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: kube-scheduler + resources: + requests: + cpu: 100m + volumeMounts: + - mountPath: /etc/kubernetes + name: k8s + readOnly: true + dnsPolicy: ClusterFirstWithHostNet + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/master: "" + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + volumes: + - hostPath: + path: /etc/kubernetes + name: k8s + updateStrategy: {} +status: + currentNumberScheduled: 0 + desiredNumberScheduled: 0 + numberMisscheduled: 0 + numberReady: 0 +` +) + +func TestBuildDaemonSet(t *testing.T) { + var tests = []struct { + component string + podBytes []byte + dsBytes []byte + }{ + { + component: kubeAPIServer, + podBytes: []byte(testAPIServerPod), + dsBytes: []byte(testAPIServerDaemonSet), + }, + { + component: kubeControllerManager, + podBytes: []byte(testControllerManagerPod), + dsBytes: []byte(testControllerManagerDaemonSet), + }, + { + component: kubeScheduler, + podBytes: []byte(testSchedulerPod), + dsBytes: []byte(testSchedulerDaemonSet), + }, + } + + for _, rt := range tests { + tempFile, err := createTempFileWithContent(rt.podBytes) + defer os.Remove(tempFile) + + podSpec, err := loadPodSpecFromFile(tempFile) + if err != nil { + t.Fatalf("couldn't load the specified Pod") + } + + ds := buildDaemonSet(rt.component, podSpec) + 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:\nexpected:\n%s\nsaw:\n%s", rt.dsBytes, dsBytes) + } + } +} + +func TestLoadPodSpecFromFile(t *testing.T) { + tests := []struct { + content string + expectError bool + }{ + { + // Good YAML + content: ` +apiVersion: v1 +kind: Pod +metadata: + name: testpod +spec: + containers: + - image: gcr.io/google_containers/busybox +`, + expectError: false, + }, + { + // Good JSON + content: ` +{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "testpod" + }, + "spec": { + "containers": [ + { + "image": "gcr.io/google_containers/busybox" + } + ] + } +}`, + expectError: false, + }, + { + // Bad PodSpec + content: ` +apiVersion: v1 +kind: Pod +metadata: + name: testpod +spec: + - image: gcr.io/google_containers/busybox +`, + expectError: true, + }, + } + + for _, rt := range tests { + tempFile, err := createTempFileWithContent([]byte(rt.content)) + defer os.Remove(tempFile) + + _, err = loadPodSpecFromFile(tempFile) + if (err != nil) != rt.expectError { + t.Errorf("failed TestLoadPodSpecFromFile:\nexpected error:\n%t\nsaw:\n%v", rt.expectError, err) + } + } +} + +func createTempFileWithContent(content []byte) (string, error) { + tempFile, err := ioutil.TempFile("", "") + if err != nil { + return "", fmt.Errorf("cannot create temporary file: %v", err) + } + if _, err = tempFile.Write([]byte(content)); err != nil { + return "", fmt.Errorf("cannot save temporary file: %v", err) + } + if err = tempFile.Close(); err != nil { + return "", fmt.Errorf("cannot close temporary file: %v", err) + } + return tempFile.Name(), nil +} diff --git a/cmd/kubeadm/app/util/BUILD b/cmd/kubeadm/app/util/BUILD index c3b5aa66ddd..73731b657cf 100644 --- a/cmd/kubeadm/app/util/BUILD +++ b/cmd/kubeadm/app/util/BUILD @@ -21,6 +21,8 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", diff --git a/hack/.linted_packages b/hack/.linted_packages index 9bb55acef13..804bc75ed4c 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -22,7 +22,9 @@ cmd/kubeadm/app/apis/kubeadm/install cmd/kubeadm/app/discovery/https cmd/kubeadm/app/phases/apiconfig cmd/kubeadm/app/phases/certs +cmd/kubeadm/app/phases/controlplane cmd/kubeadm/app/phases/kubeconfig +cmd/kubeadm/app/phases/selfhosting cmd/kubectl cmd/kubelet cmd/libs/go2idl/client-gen