622 lines
25 KiB
Go
622 lines
25 KiB
Go
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/gomega"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
rbacv1 "k8s.io/api/rbac/v1"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apimachinery/pkg/util/rand"
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
|
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
|
"github.com/karmada-io/karmada/pkg/karmadactl"
|
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
|
"github.com/karmada-io/karmada/pkg/util"
|
|
khelper "github.com/karmada-io/karmada/pkg/util/helper"
|
|
"github.com/karmada-io/karmada/pkg/util/names"
|
|
"github.com/karmada-io/karmada/test/e2e/framework"
|
|
"github.com/karmada-io/karmada/test/helper"
|
|
)
|
|
|
|
var _ = ginkgo.Describe("Karmadactl promote testing", func() {
|
|
var karmadaConfig karmadactl.KarmadaConfig
|
|
var member1 string
|
|
var member1Client kubernetes.Interface
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
|
member1 = "member1"
|
|
member1Client = framework.GetClusterClient(member1)
|
|
})
|
|
|
|
ginkgo.Context("Test promoting namespaced resource: deployment", func() {
|
|
var deployment *appsv1.Deployment
|
|
var deploymentNamespace, deploymentName string
|
|
var deploymentOpts, namespaceOpts karmadactl.CommandPromoteOption
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
deploymentNamespace = fmt.Sprintf("karmadatest-%s", rand.String(RandomStrLength))
|
|
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
|
|
deployment = helper.NewDeployment(deploymentNamespace, deploymentName)
|
|
})
|
|
|
|
ginkgo.AfterEach(func() {
|
|
deploymentGVK := schema.GroupVersionKind{
|
|
Group: "apps",
|
|
Version: "v1",
|
|
Kind: "Deployment",
|
|
}
|
|
namespaceGVK := schema.GroupVersionKind{
|
|
Group: "",
|
|
Version: "v1",
|
|
Kind: "Namespace",
|
|
}
|
|
ppName := names.GeneratePolicyName(deploymentNamespace, deploymentName, deploymentGVK.String())
|
|
cppName := names.GeneratePolicyName("", deploymentNamespace, namespaceGVK.String())
|
|
framework.RemoveDeployment(kubeClient, deploymentNamespace, deploymentName)
|
|
framework.RemovePropagationPolicy(karmadaClient, deploymentNamespace, ppName)
|
|
framework.RemoveNamespace(kubeClient, deploymentNamespace)
|
|
framework.RemoveClusterPropagationPolicy(karmadaClient, cppName)
|
|
})
|
|
|
|
ginkgo.It("Test promoting a deployment from cluster member", func() {
|
|
|
|
// Step 1, create namespace and deployment on cluster member1
|
|
ginkgo.By(fmt.Sprintf("Creating deployment %s with namespace %s not existed in karmada control plane", deploymentName, deploymentNamespace), func() {
|
|
deploymentNamespaceObj := helper.NewNamespace(deploymentNamespace)
|
|
framework.CreateNamespace(member1Client, deploymentNamespaceObj)
|
|
framework.CreateDeployment(member1Client, deployment)
|
|
})
|
|
|
|
// Step 2, promote namespace used by the deployment from member1 to karmada
|
|
ginkgo.By(fmt.Sprintf("Promoting namespace %s from member: %s to karmada control plane", deploymentNamespace, member1), func() {
|
|
namespaceOpts = karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Cluster: member1,
|
|
}
|
|
args := []string{"namespace", deploymentNamespace}
|
|
// init args: place namespace name to CommandPromoteOption.name
|
|
err := namespaceOpts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// use karmadactl to promote a namespace from member1
|
|
err = karmadactl.RunPromote(karmadaConfig, namespaceOpts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
framework.WaitNamespacePresentOnClusterByClient(kubeClient, deploymentNamespace)
|
|
})
|
|
|
|
// Step 3, promote deployment from cluster member1 to karmada
|
|
ginkgo.By(fmt.Sprintf("Promoting deployment %s from member: %s to karmada", deploymentName, member1), func() {
|
|
deploymentOpts = karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Namespace: deploymentNamespace,
|
|
Cluster: member1,
|
|
}
|
|
args := []string{"deployment", deploymentName}
|
|
// init args: place deployment name to CommandPromoteOption.name
|
|
err := deploymentOpts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// use karmadactl to promote a deployment from member1
|
|
err = karmadactl.RunPromote(karmadaConfig, deploymentOpts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Waiting for deployment %s promoted to the karmada control plane", deploymentName), func() {
|
|
gomega.Eventually(func() bool {
|
|
_, err := kubeClient.AppsV1().Deployments(deploymentNamespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
|
|
return err == nil
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Waiting for deployment(%s)'s replicas is ready", deploymentName), func() {
|
|
wantedReplicas := *deployment.Spec.Replicas
|
|
|
|
err := wait.PollImmediate(pollInterval, pollTimeout, func() (done bool, err error) {
|
|
currentDeployment, err := kubeClient.AppsV1().Deployments(deploymentNamespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
return framework.CheckDeploymentReadyStatus(currentDeployment, wantedReplicas), nil
|
|
})
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
})
|
|
})
|
|
|
|
ginkgo.Context("Test promoting cluster resources: clusterrole and clusterrolebing", func() {
|
|
|
|
var clusterRoleName, clusterRoleBindingName string
|
|
var clusterRole *rbacv1.ClusterRole
|
|
var clusterRoleBinding *rbacv1.ClusterRoleBinding
|
|
var clusterRoleOpts, clusterRoleBindingOpts karmadactl.CommandPromoteOption
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
var nameFlag = rand.String(RandomStrLength)
|
|
clusterRoleName = fmt.Sprintf("test-%s-clusterrole", nameFlag)
|
|
clusterRoleBindingName = fmt.Sprintf("test-%s-clusterrolebinding", nameFlag)
|
|
clusterRole = helper.NewClusterRole(clusterRoleName, []rbacv1.PolicyRule{
|
|
{
|
|
APIGroups: []string{"cluster.karmada.io"},
|
|
Verbs: []string{"*"},
|
|
Resources: []string{"clusters/proxy"},
|
|
ResourceNames: []string{member1},
|
|
},
|
|
})
|
|
clusterRoleBinding = helper.NewClusterRoleBinding(clusterRoleBindingName, clusterRoleName, []rbacv1.Subject{
|
|
{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: "test"},
|
|
})
|
|
})
|
|
|
|
ginkgo.AfterEach(func() {
|
|
clusterRoleGVK := schema.GroupVersionKind{
|
|
Group: "rbac.authorization.k8s.io",
|
|
Version: "v1",
|
|
Kind: "ClusterRole",
|
|
}
|
|
clusterRoleBindingGVK := schema.GroupVersionKind{
|
|
Group: "rbac.authorization.k8s.io",
|
|
Version: "v1",
|
|
Kind: "ClusterRoleBinding",
|
|
}
|
|
clusterRoleClusterPropagationPolicy := names.GeneratePolicyName("", clusterRoleName, clusterRoleGVK.String())
|
|
clusterRoleBindingClusterPropagationPolicy := names.GeneratePolicyName("", clusterRoleBindingName, clusterRoleBindingGVK.String())
|
|
framework.RemoveClusterRole(kubeClient, clusterRoleName)
|
|
framework.RemoveClusterPropagationPolicy(karmadaClient, clusterRoleClusterPropagationPolicy)
|
|
|
|
framework.RemoveClusterRoleBinding(kubeClient, clusterRoleBindingName)
|
|
framework.RemoveClusterPropagationPolicy(karmadaClient, clusterRoleBindingClusterPropagationPolicy)
|
|
})
|
|
|
|
ginkgo.It("Test promoting clusterrole and clusterrolebindings", func() {
|
|
|
|
// Step1, create clusterrole and clusterrolebinding on member1
|
|
ginkgo.By(fmt.Sprintf("Creating clusterrole and clusterrolebinding in member: %s", member1), func() {
|
|
framework.CreateClusterRole(member1Client, clusterRole)
|
|
framework.CreateClusterRoleBinding(member1Client, clusterRoleBinding)
|
|
})
|
|
|
|
// Step2, promote clusterrole and clusterrolebinding from member1
|
|
ginkgo.By(fmt.Sprintf("Promoting clusterrole %s and clusterrolebindings %s from member to karmada", clusterRoleName, clusterRoleBindingName), func() {
|
|
clusterRoleOpts = karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Cluster: member1,
|
|
}
|
|
|
|
args := []string{"clusterrole", clusterRoleName}
|
|
// init args: place clusterrole name to CommandPromoteOption.name
|
|
err := clusterRoleOpts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// use karmadactl to promote clusterrole from member1
|
|
err = karmadactl.RunPromote(karmadaConfig, clusterRoleOpts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
clusterRoleBindingOpts = karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Cluster: member1,
|
|
}
|
|
|
|
args = []string{"clusterrolebinding", clusterRoleBindingName}
|
|
// init args: place clusterrolebinding name to CommandPromoteOption.name
|
|
err = clusterRoleBindingOpts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// use karmadactl to promote clusterrolebinding from member1
|
|
err = karmadactl.RunPromote(karmadaConfig, clusterRoleBindingOpts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
// Step3, check clusterrole and clusterrolebing is promoted
|
|
ginkgo.By(fmt.Sprintf("Waiting for clusterrole %s and clusterrolebinding %s promoted to the karmada control plane", clusterRoleName, clusterRoleBindingName), func() {
|
|
gomega.Eventually(func() bool {
|
|
_, err1 := kubeClient.RbacV1().ClusterRoles().Get(context.TODO(), clusterRoleName, metav1.GetOptions{})
|
|
_, err2 := kubeClient.RbacV1().ClusterRoleBindings().Get(context.TODO(), clusterRoleBindingName, metav1.GetOptions{})
|
|
return err1 == nil && err2 == nil
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
})
|
|
|
|
})
|
|
|
|
ginkgo.Context("Test promoting namespaced resource: service", func() {
|
|
var service *corev1.Service
|
|
var serviceNamespace, serviceName, workName, esName string
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
serviceNamespace = fmt.Sprintf("karmadatest-%s", rand.String(RandomStrLength))
|
|
serviceName = serviceNamePrefix + rand.String(RandomStrLength)
|
|
service = helper.NewService(serviceNamespace, serviceName, corev1.ServiceTypeNodePort)
|
|
workName = names.GenerateWorkName(util.ServiceKind, serviceName, serviceNamespace)
|
|
esName, _ = names.GenerateExecutionSpaceName(member1)
|
|
})
|
|
|
|
ginkgo.AfterEach(func() {
|
|
framework.RemoveService(kubeClient, serviceNamespace, serviceName)
|
|
framework.RemoveNamespace(kubeClient, serviceNamespace)
|
|
})
|
|
|
|
ginkgo.It("Test promoting a service from cluster member", func() {
|
|
|
|
ginkgo.By(fmt.Sprintf("Creating service %s with namespace %s not existed in karmada control plane", serviceName, serviceNamespace), func() {
|
|
serviceNamespaceObj := helper.NewNamespace(serviceNamespace)
|
|
framework.CreateNamespace(member1Client, serviceNamespaceObj)
|
|
framework.CreateService(member1Client, service)
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Promoting namespace %s from member: %s to karmada control plane", serviceNamespace, member1), func() {
|
|
opts := karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Cluster: member1,
|
|
}
|
|
args := []string{"namespace", serviceNamespace}
|
|
err := opts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
err = karmadactl.RunPromote(karmadaConfig, opts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
framework.WaitNamespacePresentOnClusterByClient(kubeClient, serviceNamespace)
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Promoting service %s from member: %s to karmada control plane", serviceName, member1), func() {
|
|
opts := karmadactl.CommandPromoteOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
Namespace: serviceNamespace,
|
|
Cluster: member1,
|
|
}
|
|
args := []string{"service", serviceName}
|
|
err := opts.Complete(args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
|
|
err = karmadactl.RunPromote(karmadaConfig, opts, args)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Waiting for work of service %s existing in the karmada control plane", serviceNamePrefix), func() {
|
|
gomega.Eventually(func() bool {
|
|
_, err := karmadaClient.WorkV1alpha1().Works(esName).Get(context.TODO(), workName, metav1.GetOptions{})
|
|
return err == nil
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Check condition of the work generated by the service %s is `Applied`", serviceNamePrefix), func() {
|
|
gomega.Eventually(func() bool {
|
|
work, _ := karmadaClient.WorkV1alpha1().Works(esName).Get(context.TODO(), workName, metav1.GetOptions{})
|
|
applied := khelper.IsResourceApplied(&work.Status)
|
|
return applied
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
var _ = framework.SerialDescribe("Karmadactl join/unjoin testing", ginkgo.Labels{NeedCreateCluster}, func() {
|
|
ginkgo.Context("joining cluster and unjoining not ready cluster", func() {
|
|
var clusterName string
|
|
var homeDir string
|
|
var kubeConfigPath string
|
|
var clusterContext string
|
|
var controlPlane string
|
|
var deploymentName, deploymentNamespace string
|
|
var policyName, policyNamespace string
|
|
var deployment *appsv1.Deployment
|
|
var policy *policyv1alpha1.PropagationPolicy
|
|
var karmadaConfig karmadactl.KarmadaConfig
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
clusterName = "member-e2e-" + rand.String(3)
|
|
homeDir = os.Getenv("HOME")
|
|
kubeConfigPath = fmt.Sprintf("%s/.kube/%s.config", homeDir, clusterName)
|
|
clusterContext = fmt.Sprintf("kind-%s", clusterName)
|
|
controlPlane = fmt.Sprintf("%s-control-plane", clusterName)
|
|
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
|
|
deploymentNamespace = testNamespace
|
|
policyName = deploymentName
|
|
policyNamespace = testNamespace
|
|
|
|
deployment = helper.NewDeployment(deploymentNamespace, deploymentName)
|
|
policy = helper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
|
|
{
|
|
APIVersion: deployment.APIVersion,
|
|
Kind: deployment.Kind,
|
|
Name: deployment.Name,
|
|
},
|
|
}, policyv1alpha1.Placement{
|
|
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
|
|
ClusterNames: []string{clusterName},
|
|
},
|
|
})
|
|
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
|
})
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
ginkgo.By(fmt.Sprintf("Create cluster: %s", clusterName), func() {
|
|
err := createCluster(clusterName, kubeConfigPath, controlPlane, clusterContext)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
ginkgo.DeferCleanup(func() {
|
|
ginkgo.By(fmt.Sprintf("Deleting clusters: %s", clusterName), func() {
|
|
err := deleteCluster(clusterName, kubeConfigPath)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
_ = os.Remove(kubeConfigPath)
|
|
})
|
|
})
|
|
})
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
|
opts := karmadactl.CommandJoinOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterNamespace: "karmada-cluster",
|
|
ClusterName: clusterName,
|
|
ClusterContext: clusterContext,
|
|
ClusterKubeConfig: kubeConfigPath,
|
|
}
|
|
err := karmadactl.RunJoin(karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
})
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
framework.CreatePropagationPolicy(karmadaClient, policy)
|
|
framework.CreateDeployment(kubeClient, deployment)
|
|
ginkgo.DeferCleanup(func() {
|
|
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
|
|
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
|
|
})
|
|
})
|
|
|
|
ginkgo.It("Test unjoining not ready cluster", func() {
|
|
ginkgo.By("Checking cluster status collection", func() {
|
|
gomega.Eventually(func(g gomega.Gomega) (bool, error) {
|
|
cluster, err := framework.FetchCluster(karmadaClient, clusterName)
|
|
g.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
if cluster.Status.KubernetesVersion == "" {
|
|
return false, nil
|
|
}
|
|
if len(cluster.Status.APIEnablements) == 0 {
|
|
return false, nil
|
|
}
|
|
if len(cluster.Status.Conditions) == 0 {
|
|
return false, nil
|
|
}
|
|
if cluster.Status.NodeSummary == nil {
|
|
return false, nil
|
|
}
|
|
if cluster.Status.ResourceSummary == nil || len(cluster.Status.ResourceSummary.AllocatableModelings) == 0 {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
ginkgo.By("Waiting for deployment have been propagated to the member cluster.", func() {
|
|
klog.Infof("Waiting for deployment(%s/%s) synced on cluster(%s)", deploymentNamespace, deploymentName, clusterName)
|
|
|
|
clusterConfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
clusterClient := kubernetes.NewForConfigOrDie(clusterConfig)
|
|
|
|
gomega.Eventually(func() bool {
|
|
_, err := clusterClient.AppsV1().Deployments(deploymentNamespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
|
|
return err == nil
|
|
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Disable cluster: %s", clusterName), func() {
|
|
err := disableCluster(controlPlaneClient, clusterName)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
framework.WaitClusterFitWith(controlPlaneClient, clusterName, func(cluster *clusterv1alpha1.Cluster) bool {
|
|
return meta.IsStatusConditionPresentAndEqual(cluster.Status.Conditions, clusterv1alpha1.ClusterConditionReady, metav1.ConditionFalse)
|
|
})
|
|
})
|
|
|
|
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
|
opts := karmadactl.CommandUnjoinOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterNamespace: "karmada-cluster",
|
|
ClusterName: clusterName,
|
|
ClusterContext: clusterContext,
|
|
ClusterKubeConfig: kubeConfigPath,
|
|
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
|
}
|
|
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
var _ = framework.SerialDescribe("Karmadactl cordon/uncordon testing", ginkgo.Labels{NeedCreateCluster}, func() {
|
|
var member1 string
|
|
var controlPlane string
|
|
var clusterName string
|
|
var homeDir string
|
|
var kubeConfigPath string
|
|
var clusterContext string
|
|
var deploymentName, deploymentNamespace string
|
|
var policyName, policyNamespace string
|
|
var deployment *appsv1.Deployment
|
|
var policy *policyv1alpha1.PropagationPolicy
|
|
var karmadaConfig karmadactl.KarmadaConfig
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
member1 = "member1"
|
|
clusterName = "member-e2e-" + rand.String(3)
|
|
homeDir = os.Getenv("HOME")
|
|
kubeConfigPath = fmt.Sprintf("%s/.kube/%s.config", homeDir, clusterName)
|
|
controlPlane = fmt.Sprintf("%s-control-plane", clusterName)
|
|
clusterContext = fmt.Sprintf("kind-%s", clusterName)
|
|
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
|
|
deploymentNamespace = testNamespace
|
|
policyName = deploymentName
|
|
policyNamespace = testNamespace
|
|
|
|
deployment = helper.NewDeployment(deploymentNamespace, deploymentName)
|
|
policy = helper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
|
|
{
|
|
APIVersion: deployment.APIVersion,
|
|
Kind: deployment.Kind,
|
|
Name: deployment.Name,
|
|
},
|
|
}, policyv1alpha1.Placement{
|
|
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
|
|
ClusterNames: []string{member1, clusterName},
|
|
},
|
|
ReplicaScheduling: &policyv1alpha1.ReplicaSchedulingStrategy{
|
|
ReplicaSchedulingType: policyv1alpha1.ReplicaSchedulingTypeDuplicated,
|
|
},
|
|
})
|
|
karmadaConfig = karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
|
})
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
ginkgo.By(fmt.Sprintf("Creating cluster: %s", clusterName), func() {
|
|
err := createCluster(clusterName, kubeConfigPath, controlPlane, clusterContext)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
ginkgo.By(fmt.Sprintf("Joinning cluster: %s", clusterName), func() {
|
|
karmadaConfig := karmadactl.NewKarmadaConfig(clientcmd.NewDefaultPathOptions())
|
|
opts := karmadactl.CommandJoinOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterNamespace: "karmada-cluster",
|
|
ClusterName: clusterName,
|
|
ClusterContext: clusterContext,
|
|
ClusterKubeConfig: kubeConfigPath,
|
|
}
|
|
err := karmadactl.RunJoin(karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
// When a newly joined cluster is unready at the beginning, the scheduler will ignore it.
|
|
ginkgo.By(fmt.Sprintf("wait cluster %s ready", clusterName), func() {
|
|
framework.WaitClusterFitWith(controlPlaneClient, clusterName, func(cluster *clusterv1alpha1.Cluster) bool {
|
|
return meta.IsStatusConditionPresentAndEqual(cluster.Status.Conditions, clusterv1alpha1.ClusterConditionReady, metav1.ConditionTrue)
|
|
})
|
|
})
|
|
ginkgo.DeferCleanup(func() {
|
|
ginkgo.By(fmt.Sprintf("Unjoinning cluster: %s", clusterName), func() {
|
|
opts := karmadactl.CommandUnjoinOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterNamespace: "karmada-cluster",
|
|
ClusterName: clusterName,
|
|
ClusterContext: clusterContext,
|
|
ClusterKubeConfig: kubeConfigPath,
|
|
Wait: 5 * options.DefaultKarmadactlCommandDuration,
|
|
}
|
|
err := karmadactl.RunUnjoin(karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
ginkgo.By(fmt.Sprintf("Deleting clusters: %s", clusterName), func() {
|
|
err := deleteCluster(clusterName, kubeConfigPath)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
_ = os.Remove(kubeConfigPath)
|
|
})
|
|
})
|
|
})
|
|
ginkgo.Context("cordon cluster", func() {
|
|
ginkgo.BeforeEach(func() {
|
|
opts := karmadactl.CommandCordonOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterName: clusterName,
|
|
}
|
|
err := karmadactl.RunCordonOrUncordon(karmadactl.DesiredCordon, karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
ginkgo.By("cluster should have a taint", func() {
|
|
clusterObj := &clusterv1alpha1.Cluster{}
|
|
err := controlPlaneClient.Get(context.TODO(), client.ObjectKey{Name: clusterName}, clusterObj)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
taints := clusterObj.Spec.Taints
|
|
var unschedulable corev1.Taint
|
|
for index := range taints {
|
|
if taints[index].Key == clusterv1alpha1.TaintClusterUnscheduler {
|
|
unschedulable = taints[index]
|
|
break
|
|
}
|
|
}
|
|
gomega.Expect(unschedulable).ShouldNot(gomega.BeNil())
|
|
gomega.Expect(unschedulable.Effect).Should(gomega.Equal(corev1.TaintEffectNoSchedule))
|
|
})
|
|
})
|
|
|
|
ginkgo.It(fmt.Sprintf("deploy deployment should not schedule to cordon cluster %s", clusterName), func() {
|
|
framework.CreatePropagationPolicy(karmadaClient, policy)
|
|
framework.CreateDeployment(kubeClient, deployment)
|
|
ginkgo.DeferCleanup(func() {
|
|
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
|
|
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
|
|
})
|
|
targetClusters := framework.ExtractTargetClustersFrom(controlPlaneClient, deployment)
|
|
gomega.Expect(targetClusters).ShouldNot(gomega.ContainElement(clusterName))
|
|
})
|
|
|
|
ginkgo.It("uncordon cluster", func() {
|
|
opts := karmadactl.CommandCordonOption{
|
|
GlobalCommandOptions: options.GlobalCommandOptions{
|
|
KarmadaContext: karmadaContext,
|
|
},
|
|
DryRun: false,
|
|
ClusterName: clusterName,
|
|
}
|
|
err := karmadactl.RunCordonOrUncordon(karmadactl.DesiredUnCordon, karmadaConfig, opts)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
ginkgo.By(fmt.Sprintf("cluster %s taint will be removed", clusterName), func() {
|
|
clusterObj := &clusterv1alpha1.Cluster{}
|
|
err := controlPlaneClient.Get(context.TODO(), client.ObjectKey{Name: clusterName}, clusterObj)
|
|
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
|
gomega.Expect(clusterObj.Spec.Taints).Should(gomega.BeEmpty())
|
|
})
|
|
|
|
framework.CreatePropagationPolicy(karmadaClient, policy)
|
|
framework.CreateDeployment(kubeClient, deployment)
|
|
ginkgo.DeferCleanup(func() {
|
|
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
|
|
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
|
|
})
|
|
ginkgo.By(fmt.Sprintf("deployment will schedule to cluster %s", clusterName), func() {
|
|
targetClusters := framework.ExtractTargetClustersFrom(controlPlaneClient, deployment)
|
|
gomega.Expect(targetClusters).Should(gomega.ContainElement(clusterName))
|
|
})
|
|
})
|
|
})
|
|
})
|