From e26162726057f5bad369c72f42f2be9cfccd30dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Wed, 1 Feb 2017 23:54:31 +0200 Subject: [PATCH] Remove unused helpers in apiclient.go and deploy the dummy deployment from a yaml spec --- cmd/kubeadm/app/master/apiclient.go | 110 ++++--------- cmd/kubeadm/app/master/apiclient_test.go | 190 ----------------------- cmd/kubeadm/app/master/templates.go | 43 +++++ 3 files changed, 73 insertions(+), 270 deletions(-) delete mode 100644 cmd/kubeadm/app/master/apiclient_test.go create mode 100644 cmd/kubeadm/app/master/templates.go diff --git a/cmd/kubeadm/app/master/apiclient.go b/cmd/kubeadm/app/master/apiclient.go index 0b960d88fe1..214b71567f5 100644 --- a/cmd/kubeadm/app/master/apiclient.go +++ b/cmd/kubeadm/app/master/apiclient.go @@ -17,31 +17,30 @@ limitations under the License. package master import ( - "encoding/json" "fmt" + "runtime" "time" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kuberuntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/clientcmd" - "k8s.io/kubernetes/cmd/kubeadm/app/images" + kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" + kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" + kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1" extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" ) -const apiCallRetryInterval = 500 * time.Millisecond - func CreateClientFromFile(path string) (*clientset.Clientset, error) { adminKubeconfig, err := clientcmd.LoadFromFile(path) if err != nil { return nil, fmt.Errorf("failed to load admin kubeconfig [%v]", err) } - adminClientConfig, err := clientcmd.NewDefaultClientConfig( - *adminKubeconfig, - &clientcmd.ConfigOverrides{}, - ).ClientConfig() + adminClientConfig, err := clientcmd.NewDefaultClientConfig(*adminKubeconfig, &clientcmd.ConfigOverrides{}).ClientConfig() if err != nil { return nil, fmt.Errorf("failed to create API client configuration [%v]", err) } @@ -64,7 +63,7 @@ func CreateClientAndWaitForAPI(file string) (*clientset.Clientset, error) { fmt.Println("[apiclient] Waiting for at least one node to register and become ready") start := time.Now() - wait.PollInfinite(apiCallRetryInterval, func() (bool, error) { + wait.PollInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { nodeList, err := client.Nodes().List(metav1.ListOptions{}) if err != nil { fmt.Println("[apiclient] Temporarily unable to list nodes (will retry)") @@ -83,21 +82,16 @@ func CreateClientAndWaitForAPI(file string) (*clientset.Clientset, error) { return true, nil }) - createDummyDeployment(client) + if err := createAndWaitForADummyDeployment(client); err != nil { + return nil, err + } return client, nil } -func standardLabels(n string) map[string]string { - return map[string]string{ - "component": n, "name": n, "k8s-app": n, - "kubernetes.io/cluster-service": "true", "tier": "node", - } -} - func WaitForAPI(client *clientset.Clientset) { start := time.Now() - wait.PollInfinite(apiCallRetryInterval, func() (bool, error) { + wait.PollInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { // TODO: use /healthz API instead of this cs, err := client.ComponentStatuses().List(metav1.ListOptions{}) if err != nil { @@ -125,76 +119,31 @@ func WaitForAPI(client *clientset.Clientset) { }) } -func NewDaemonSet(daemonName string, podSpec v1.PodSpec) *extensions.DaemonSet { - l := standardLabels(daemonName) - return &extensions.DaemonSet{ - ObjectMeta: metav1.ObjectMeta{Name: daemonName}, - Spec: extensions.DaemonSetSpec{ - Selector: &metav1.LabelSelector{MatchLabels: l}, - Template: v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: l}, - Spec: podSpec, - }, - }, - } -} - -func NewService(serviceName string, spec v1.ServiceSpec) *v1.Service { - l := standardLabels(serviceName) - return &v1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Labels: l, - }, - Spec: spec, - } -} - -func NewDeployment(deploymentName string, replicas int32, podSpec v1.PodSpec) *extensions.Deployment { - l := standardLabels(deploymentName) - return &extensions.Deployment{ - ObjectMeta: metav1.ObjectMeta{Name: deploymentName}, - Spec: extensions.DeploymentSpec{ - Replicas: &replicas, - Selector: &metav1.LabelSelector{MatchLabels: l}, - Template: v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{Labels: l}, - Spec: podSpec, - }, - }, - } -} - -func SetMasterTaintTolerations(meta *metav1.ObjectMeta) { - tolerationsAnnotation, _ := json.Marshal([]v1.Toleration{{Key: "dedicated", Value: "master", Effect: "NoSchedule"}}) - if meta.Annotations == nil { - meta.Annotations = map[string]string{} - } - meta.Annotations[v1.TolerationsAnnotationKey] = string(tolerationsAnnotation) -} - -func createDummyDeployment(client *clientset.Clientset) { - fmt.Println("[apiclient] Creating a test deployment") - dummyDeployment := NewDeployment("dummy", 1, v1.PodSpec{ - HostNetwork: true, - SecurityContext: &v1.PodSecurityContext{}, - Containers: []v1.Container{{ - Name: "dummy", - Image: images.GetAddonImage("pause"), - }}, +func createAndWaitForADummyDeployment(client *clientset.Clientset) error { + dummyDeploymentBytes, err := kubeadmutil.ParseTemplate(DummyDeployment, struct{ ImageRepository, Arch string }{ + ImageRepository: kubeadmapi.GlobalEnvParams.RepositoryPrefix, + Arch: runtime.GOARCH, }) + if err != nil { + return fmt.Errorf("error when parsing dummy deployment template: %v", err) + } - wait.PollInfinite(apiCallRetryInterval, func() (bool, error) { + dummyDeployment := &extensions.Deployment{} + if err := kuberuntime.DecodeInto(api.Codecs.UniversalDecoder(), dummyDeploymentBytes, dummyDeployment); err != nil { + return fmt.Errorf("unable to decode dummy deployment %v", err) + } + + wait.PollInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { // TODO: we should check the error, as some cases may be fatal - if _, err := client.Extensions().Deployments(metav1.NamespaceSystem).Create(dummyDeployment); err != nil { + if _, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Create(dummyDeployment); err != nil { fmt.Printf("[apiclient] Failed to create test deployment [%v] (will retry)\n", err) return false, nil } return true, nil }) - wait.PollInfinite(apiCallRetryInterval, func() (bool, error) { - d, err := client.Extensions().Deployments(metav1.NamespaceSystem).Get("dummy", metav1.GetOptions{}) + wait.PollInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { + d, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Get("dummy", metav1.GetOptions{}) if err != nil { fmt.Printf("[apiclient] Failed to get test deployment [%v] (will retry)\n", err) return false, nil @@ -208,7 +157,8 @@ func createDummyDeployment(client *clientset.Clientset) { fmt.Println("[apiclient] Test deployment succeeded") // TODO: In the future, make sure the ReplicaSet and Pod are garbage collected - if err := client.Extensions().Deployments(metav1.NamespaceSystem).Delete("dummy", &metav1.DeleteOptions{}); err != nil { + if err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Delete("dummy", &metav1.DeleteOptions{}); err != nil { fmt.Printf("[apiclient] Failed to delete test deployment [%v] (will ignore)\n", err) } + return nil } diff --git a/cmd/kubeadm/app/master/apiclient_test.go b/cmd/kubeadm/app/master/apiclient_test.go deleted file mode 100644 index 9936e965062..00000000000 --- a/cmd/kubeadm/app/master/apiclient_test.go +++ /dev/null @@ -1,190 +0,0 @@ -/* -Copyright 2016 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 master - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api/v1" -) - -func TestStandardLabels(t *testing.T) { - var tests = []struct { - n string - expected string - }{ - { - n: "foo", - expected: "foo", - }, - { - n: "bar", - expected: "bar", - }, - } - - for _, rt := range tests { - actual := standardLabels(rt.n) - if actual["component"] != rt.expected { - t.Errorf( - "failed standardLabels:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual["component"], - ) - } - if actual["name"] != rt.expected { - t.Errorf( - "failed standardLabels:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual["name"], - ) - } - if actual["k8s-app"] != rt.expected { - t.Errorf( - "failed standardLabels:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual["k8s-app"], - ) - } - } -} - -func TestNewDaemonSet(t *testing.T) { - var tests = []struct { - dn string - expected string - }{ - { - dn: "foo", - expected: "foo", - }, - { - dn: "bar", - expected: "bar", - }, - } - - for _, rt := range tests { - p := v1.PodSpec{} - actual := NewDaemonSet(rt.dn, p) - if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected { - t.Errorf( - "failed NewDaemonSet:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["k8s-app"], - ) - } - if actual.Spec.Selector.MatchLabels["component"] != rt.expected { - t.Errorf( - "failed NewDaemonSet:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["component"], - ) - } - if actual.Spec.Selector.MatchLabels["name"] != rt.expected { - t.Errorf( - "failed NewDaemonSet:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["name"], - ) - } - } -} - -func TestNewService(t *testing.T) { - var tests = []struct { - dn string - expected string - }{ - { - dn: "foo", - expected: "foo", - }, - { - dn: "bar", - expected: "bar", - }, - } - - for _, rt := range tests { - p := v1.ServiceSpec{} - actual := NewService(rt.dn, p) - if actual.ObjectMeta.Labels["k8s-app"] != rt.expected { - t.Errorf( - "failed NewService:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.ObjectMeta.Labels["k8s-app"], - ) - } - if actual.ObjectMeta.Labels["component"] != rt.expected { - t.Errorf( - "failed NewService:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.ObjectMeta.Labels["component"], - ) - } - if actual.ObjectMeta.Labels["name"] != rt.expected { - t.Errorf( - "failed NewService:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.ObjectMeta.Labels["name"], - ) - } - } -} - -func TestNewDeployment(t *testing.T) { - var tests = []struct { - dn string - expected string - }{ - { - dn: "foo", - expected: "foo", - }, - { - dn: "bar", - expected: "bar", - }, - } - - for _, rt := range tests { - p := v1.PodSpec{} - actual := NewDeployment(rt.dn, 1, p) - if actual.Spec.Selector.MatchLabels["k8s-app"] != rt.expected { - t.Errorf( - "failed NewDeployment:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["k8s-app"], - ) - } - if actual.Spec.Selector.MatchLabels["component"] != rt.expected { - t.Errorf( - "failed NewDeployment:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["component"], - ) - } - if actual.Spec.Selector.MatchLabels["name"] != rt.expected { - t.Errorf( - "failed NewDeployment:\n\texpected: %s\n\t actual: %s", - rt.expected, - actual.Spec.Selector.MatchLabels["name"], - ) - } - } -} diff --git a/cmd/kubeadm/app/master/templates.go b/cmd/kubeadm/app/master/templates.go new file mode 100644 index 00000000000..5b2e88301cf --- /dev/null +++ b/cmd/kubeadm/app/master/templates.go @@ -0,0 +1,43 @@ +/* +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 master + +const ( + DummyDeployment = ` +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: dummy + name: dummy + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: dummy + template: + metadata: + labels: + app: dummy + spec: + containers: + - image: {{ .ImageRepository }}/pause-{{ .Arch }}:3.0 + name: dummy + hostNetwork: true +` +)