github.com/SUSE/skuba@v1.4.17/pkg/skuba/actions/node/remove/remove_test.go (about) 1 /* 2 * Copyright (c) 2019 SUSE LLC. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package remove 19 20 import ( 21 "crypto/sha1" 22 "fmt" 23 "testing" 24 25 batchv1 "k8s.io/api/batch/v1" 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "k8s.io/client-go/kubernetes/fake" 29 ) 30 31 func Test_RemoveNode(t *testing.T) { 32 cm := &corev1.ConfigMap{ 33 ObjectMeta: metav1.ObjectMeta{ 34 Name: "kubeadm-config", 35 Namespace: metav1.NamespaceSystem, 36 }, 37 Data: map[string]string{"ClusterConfiguration": ` 38 apiVersion: kubeadm.k8s.io/v1beta1 39 kind: ClusterConfiguration 40 kubernetesVersion: "v1.17.13" 41 apiServer: 42 extraArgs: 43 advertiseAddress: 1.2.3.4 44 `}, 45 } 46 47 jobSpec := batchv1.JobSpec{ 48 Template: corev1.PodTemplateSpec{ 49 Spec: corev1.PodSpec{ 50 Containers: []corev1.Container{ 51 { 52 Name: "fake", 53 Image: "fake", 54 Command: []string{"/bin/bash"}, 55 }, 56 }, 57 RestartPolicy: corev1.RestartPolicyNever, 58 Volumes: []corev1.Volume{}, 59 NodeSelector: map[string]string{ 60 "kubernetes.io/hostname": "fake", 61 }, 62 Tolerations: []corev1.Toleration{ 63 { 64 Operator: corev1.TolerationOpExists, 65 }, 66 }, 67 }, 68 }, 69 } 70 71 master1 := corev1.Node{ 72 ObjectMeta: metav1.ObjectMeta{ 73 Name: "master-1", 74 Labels: map[string]string{"node-role.kubernetes.io/master": ""}, 75 }, 76 } 77 78 master2 := corev1.Node{ 79 ObjectMeta: metav1.ObjectMeta{ 80 Name: "master-2", 81 Labels: map[string]string{"node-role.kubernetes.io/master": ""}, 82 }, 83 } 84 85 worker1 := corev1.Node{ 86 ObjectMeta: metav1.ObjectMeta{ 87 Name: "worker-1", 88 }, 89 } 90 91 worker2 := corev1.Node{ 92 ObjectMeta: metav1.ObjectMeta{ 93 Name: "worker-2", 94 }, 95 } 96 97 test := []struct { 98 name string 99 target string 100 executer []string 101 clientset *fake.Clientset 102 errorExpected bool 103 errorMessage string 104 }{ 105 { 106 name: "should remove master from cluster", 107 target: master2.Name, 108 executer: []string{master1.Name, master2.Name}, 109 clientset: fake.NewSimpleClientset(&corev1.NodeList{Items: []corev1.Node{master1, master2}}), 110 errorExpected: false, 111 }, 112 { 113 name: "should fail when remove last master from cluster", 114 target: master1.Name, 115 clientset: fake.NewSimpleClientset(&corev1.NodeList{Items: []corev1.Node{master1}}), 116 errorExpected: true, 117 errorMessage: "could not remove last master of the cluster", 118 }, 119 { 120 name: "should fail when remove node does not exist", 121 target: "not-exist", 122 executer: []string{master1.Name}, 123 clientset: fake.NewSimpleClientset(&corev1.NodeList{Items: []corev1.Node{master1}}), 124 errorExpected: true, 125 errorMessage: "[remove-node] could not get node not-exist: nodes \"not-exist\" not found", 126 }, 127 { 128 name: "should remove worker from cluster", 129 target: worker2.Name, 130 executer: []string{master1.Name}, 131 clientset: fake.NewSimpleClientset(&corev1.NodeList{Items: []corev1.Node{master1, worker1, worker2}}), 132 errorExpected: false, 133 }, 134 } 135 136 for _, tt := range test { 137 tt := tt // Parallel testing 138 t.Run(tt.name, func(t *testing.T) { 139 //nolint:errcheck 140 tt.clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(cm) 141 142 shaTarget := fmt.Sprintf("%x", sha1.Sum([]byte(tt.target))) 143 shaExecuter := "" 144 for _, executer := range tt.executer { 145 shaExecuter = fmt.Sprintf("%x", sha1.Sum([]byte(executer))) 146 //nolint:errcheck 147 tt.clientset.BatchV1().Jobs(metav1.NamespaceSystem).Create(&batchv1.Job{ 148 ObjectMeta: metav1.ObjectMeta{ 149 Name: fmt.Sprintf("caasp-remove-etcd-member-%.10s-from-%.10s", shaTarget, shaExecuter), 150 Namespace: metav1.NamespaceSystem, 151 }, 152 Spec: jobSpec, 153 Status: batchv1.JobStatus{Active: 1}, 154 }) 155 } 156 //nolint:errcheck 157 tt.clientset.BatchV1().Jobs(metav1.NamespaceSystem).Create(&batchv1.Job{ 158 ObjectMeta: metav1.ObjectMeta{ 159 Name: fmt.Sprintf("caasp-kubelet-disarm-%s", shaTarget), 160 Namespace: metav1.NamespaceSystem, 161 }, 162 Spec: jobSpec, 163 }) 164 165 err := Remove(tt.clientset, tt.target, 0) 166 if tt.errorExpected && err == nil { 167 t.Errorf("error expected on %s, but no error reported", tt.name) 168 return 169 } else if !tt.errorExpected && err != nil { 170 t.Errorf("error not expected on %s, but an error was reported (%s)", tt.name, err.Error()) 171 return 172 } else if tt.errorExpected && err.Error() != tt.errorMessage { 173 t.Errorf("returned error (%v) does not match the expected one (%v)", err.Error(), tt.errorMessage) 174 return 175 } 176 }) 177 } 178 }