@@ -1154,6 +1154,163 @@ var _ = ginkgo.Describe("Karmadactl options testing", func() {
1154
1154
})
1155
1155
})
1156
1156
1157
+ var _ = framework .SerialDescribe ("Karmadactl taint testing" , ginkgo.Labels {NeedCreateCluster }, func () {
1158
+ ginkgo .Context ("Test karmadactl taint command with different effects" , func () {
1159
+ var (
1160
+ newClusterName , clusterContext string
1161
+ homeDir , kubeConfigPath , controlPlane string
1162
+ taintKey = "environment"
1163
+ taintProductionValue = "production"
1164
+ taintTestValue = "test"
1165
+ )
1166
+
1167
+ ginkgo .BeforeEach (func () {
1168
+ newClusterName = "member-e2e-" + rand .String (3 )
1169
+ homeDir = os .Getenv ("HOME" )
1170
+ kubeConfigPath = fmt .Sprintf ("%s/.kube/%s.config" , homeDir , newClusterName )
1171
+ controlPlane = fmt .Sprintf ("%s-control-plane" , newClusterName )
1172
+ clusterContext = fmt .Sprintf ("kind-%s" , newClusterName )
1173
+ })
1174
+
1175
+ ginkgo .BeforeEach (func () {
1176
+ ginkgo .By (fmt .Sprintf ("Creating cluster: %s" , newClusterName ), func () {
1177
+ err := createCluster (newClusterName , kubeConfigPath , controlPlane , clusterContext )
1178
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1179
+ })
1180
+
1181
+ ginkgo .By (fmt .Sprintf ("Joining cluster: %s" , newClusterName ), func () {
1182
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout ,
1183
+ "join" , "--cluster-kubeconfig" , kubeConfigPath , "--cluster-context" , clusterContext , "--cluster-namespace" , "karmada-cluster" , newClusterName )
1184
+ _ , err := cmd .ExecOrDie ()
1185
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1186
+ })
1187
+
1188
+ ginkgo .By (fmt .Sprintf ("wait cluster %s ready" , newClusterName ), func () {
1189
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1190
+ return meta .IsStatusConditionPresentAndEqual (cluster .Status .Conditions , clusterv1alpha1 .ClusterConditionReady , metav1 .ConditionTrue )
1191
+ })
1192
+ })
1193
+
1194
+ ginkgo .DeferCleanup (func () {
1195
+ ginkgo .By (fmt .Sprintf ("Unjoinning cluster: %s" , newClusterName ), func () {
1196
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , 5 * options .DefaultKarmadactlCommandDuration ,
1197
+ "unjoin" , "--cluster-kubeconfig" , kubeConfigPath , "--cluster-context" , clusterContext , "--cluster-namespace" , "karmada-cluster" , newClusterName )
1198
+ _ , err := cmd .ExecOrDie ()
1199
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1200
+ })
1201
+
1202
+ ginkgo .By (fmt .Sprintf ("Deleting clusters: %s" , newClusterName ), func () {
1203
+ err := deleteCluster (newClusterName , kubeConfigPath )
1204
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1205
+ _ = os .Remove (kubeConfigPath )
1206
+ })
1207
+ })
1208
+ })
1209
+
1210
+ ginkgo .It ("should handle taint correctly" , func () {
1211
+ // testTaintEffect is a reusable function for testing taints on a given effect.
1212
+ testTaintEffect := func (effect corev1.TaintEffect ) {
1213
+ productionTaint := fmt .Sprintf ("%s=%s:%s" , taintKey , taintProductionValue , effect )
1214
+ testTaint := fmt .Sprintf ("%s=%s:%s" , taintKey , taintTestValue , effect )
1215
+
1216
+ ginkgo .By (fmt .Sprintf ("Verifying that %s taint is not applied during dry-run mode" , productionTaint ), func () {
1217
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , productionTaint , "--dry-run" )
1218
+ output , err := cmd .ExecOrDie ()
1219
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1220
+ gomega .Expect (strings .Contains (output , fmt .Sprintf ("cluster/%s tainted" , newClusterName ))).Should (gomega .BeTrue ())
1221
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1222
+ for _ , taint := range cluster .Spec .Taints {
1223
+ if taint .Key == taintKey && taint .Value == taintProductionValue && taint .Effect == effect {
1224
+ return false
1225
+ }
1226
+ }
1227
+ return true
1228
+ })
1229
+ })
1230
+
1231
+ ginkgo .By (fmt .Sprintf ("Applying %s taint to the cluster" , productionTaint ), func () {
1232
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , productionTaint )
1233
+ output , err := cmd .ExecOrDie ()
1234
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1235
+ gomega .Expect (strings .Contains (output , fmt .Sprintf ("cluster/%s tainted" , newClusterName ))).Should (gomega .BeTrue ())
1236
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1237
+ for _ , taint := range cluster .Spec .Taints {
1238
+ if taint .Key == taintKey && taint .Value == taintProductionValue && taint .Effect == effect {
1239
+ return true
1240
+ }
1241
+ }
1242
+ return false
1243
+ })
1244
+ })
1245
+
1246
+ ginkgo .By (fmt .Sprintf ("Overwriting %s taint with %s taint without --overwrite flag" , productionTaint , testTaint ), func () {
1247
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , testTaint )
1248
+ _ , err := cmd .ExecOrDie ()
1249
+ gomega .Expect (err ).Should (gomega .HaveOccurred ())
1250
+ gomega .Expect (strings .Contains (err .Error (), fmt .Sprintf ("cluster %s already has environment taint(s) with same effect(s) and --overwrite is false" , newClusterName ))).Should (gomega .BeTrue ())
1251
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1252
+ for _ , taint := range cluster .Spec .Taints {
1253
+ if taint .Key == taintKey && taint .Value == taintProductionValue && taint .Effect == effect {
1254
+ return true
1255
+ }
1256
+ }
1257
+ return false
1258
+ })
1259
+ })
1260
+
1261
+ ginkgo .By (fmt .Sprintf ("Overwriting %s taint with %s taint using --overwrite flag" , productionTaint , testTaint ), func () {
1262
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , testTaint , "--overwrite" )
1263
+ output , err := cmd .ExecOrDie ()
1264
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1265
+ gomega .Expect (strings .Contains (output , fmt .Sprintf ("cluster/%s modified" , newClusterName ))).Should (gomega .BeTrue ())
1266
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1267
+ for _ , taint := range cluster .Spec .Taints {
1268
+ if taint .Key == taintKey && taint .Value == taintTestValue && taint .Effect == effect {
1269
+ return true
1270
+ }
1271
+ }
1272
+ return false
1273
+ })
1274
+ })
1275
+
1276
+ ginkgo .By (fmt .Sprintf ("Removing %s taint from the cluster" , testTaint ), func () {
1277
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , fmt .Sprintf ("%s-" , testTaint ))
1278
+ output , err := cmd .ExecOrDie ()
1279
+ gomega .Expect (err ).ShouldNot (gomega .HaveOccurred ())
1280
+ gomega .Expect (strings .Contains (output , "untainted" )).Should (gomega .BeTrue ())
1281
+ framework .WaitClusterFitWith (controlPlaneClient , newClusterName , func (cluster * clusterv1alpha1.Cluster ) bool {
1282
+ for _ , taint := range cluster .Spec .Taints {
1283
+ if taint .Key == taintKey && taint .Value == taintTestValue && taint .Effect == effect {
1284
+ return false
1285
+ }
1286
+ }
1287
+ return true
1288
+ })
1289
+ })
1290
+
1291
+ ginkgo .By ("Returning an error for invalid flag in taint command" , func () {
1292
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , newClusterName , productionTaint , "--invalidflag" )
1293
+ _ , err := cmd .ExecOrDie ()
1294
+ gomega .Expect (err ).Should (gomega .HaveOccurred ())
1295
+ gomega .Expect (strings .Contains (err .Error (), "unknown flag: --invalidflag" )).Should (gomega .BeTrue ())
1296
+ })
1297
+
1298
+ ginkgo .By ("Returning an error if cluster does not exist" , func () {
1299
+ nonExistentCluster := "non-existent-cluster"
1300
+ cmd := framework .NewKarmadactlCommand (kubeconfig , karmadaContext , karmadactlPath , "" , karmadactlTimeout , "taint" , "clusters" , nonExistentCluster , productionTaint )
1301
+ _ , err := cmd .ExecOrDie ()
1302
+ gomega .Expect (err ).Should (gomega .HaveOccurred ())
1303
+ gomega .Expect (strings .Contains (err .Error (), fmt .Sprintf ("clusters.cluster.karmada.io \" %s\" not found" , nonExistentCluster ))).Should (gomega .BeTrue ())
1304
+ })
1305
+ }
1306
+
1307
+ // Call testTaintEffect function for each taint effect: NoSchedule, NoExecute.
1308
+ testTaintEffect (corev1 .TaintEffectNoSchedule )
1309
+ testTaintEffect (corev1 .TaintEffectNoExecute )
1310
+ })
1311
+ })
1312
+ })
1313
+
1157
1314
// extractTokenIDAndSecret extracts the token ID and Secret from the output string.
1158
1315
// It assumes the output format is "tokenID.tokenSecret".
1159
1316
//
0 commit comments