Merge pull request #5250 from mohamedawnallah/testKarmadactlApplyCommand

test/e2e/karmadactl_test.go: test apply command
This commit is contained in:
karmada-bot 2024-08-20 20:05:39 +08:00 committed by GitHub
commit 23cbfdc527
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 182 additions and 1 deletions

View File

@ -29,6 +29,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -39,6 +40,7 @@ import (
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
@ -53,7 +55,8 @@ import (
)
const (
karmadactlTimeout = time.Second * 10
karmadactlTimeout = time.Second * 10
PropagationPolicyPattern = `propagationpolicy\.policy\.karmada\.io\/([a-zA-Z0-9\-]+)`
)
var _ = ginkgo.Describe("Karmadactl promote testing", func() {
@ -1373,6 +1376,184 @@ var _ = framework.SerialDescribe("Karmadactl taint testing", ginkgo.Labels{NeedC
})
})
var _ = ginkgo.Describe("Karmadactl apply testing", func() {
var (
member1Name string
member1Client kubernetes.Interface
deploymentManifest string
deployment *appsv1.Deployment
)
ginkgo.BeforeEach(func() {
member1Name = framework.ClusterNames()[0]
member1Client = framework.GetClusterClient(member1Name)
})
ginkgo.BeforeEach(func() {
deployment = helper.NewDeployment(testNamespace, deploymentNamePrefix+rand.String(RandomStrLength))
deploymentManifest = fmt.Sprintf("/tmp/%s.yaml", deployment.Name)
err := WriteYamlToFile(deployment, deploymentManifest)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
ginkgo.DeferCleanup(func() {
os.Remove(deploymentManifest)
})
})
ginkgo.It("should apply configuration without propagating into member clusters", func() {
// Apply configuration without propagation to member clusters.
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", deploymentManifest)
output, err := cmd.ExecOrDie()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("deployment.apps/%s created", deployment.Name)))
defer framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
// Check that the deployment is created on karmada control plane.
framework.WaitDeploymentFitWith(kubeClient, deployment.Namespace, deployment.Name, func(_ *appsv1.Deployment) bool {
return true
})
})
ginkgo.It("should apply configuration with propagation into specific member clusters", func() {
// Apply configuration with propagation to member1 cluster.
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", deploymentManifest, "--cluster", member1Name)
output, err := cmd.ExecOrDie()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("deployment.apps/%s created", deployment.Name)))
gomega.Expect(output).Should(gomega.MatchRegexp(PropagationPolicyPattern + ` created`))
defer framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
// Extract propagation policy name.
propagationPolicyName, err := extractPropagationPolicyName(output)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
defer framework.RemovePropagationPolicy(karmadaClient, testNamespace, propagationPolicyName)
// Check that the propagation policy is created on the karmada control plane in the given namespace.
framework.WaitPropagationPolicyFitWith(karmadaClient, testNamespace, propagationPolicyName, func(_ *policyv1alpha1.PropagationPolicy) bool {
return true
})
// Check that the deployment is created on the karmada control plane.
framework.WaitDeploymentFitWith(kubeClient, deployment.Namespace, deployment.Name, func(_ *appsv1.Deployment) bool {
return true
})
// Check that the deployment is propagated to the specified member1 cluster.
framework.WaitClusterFitWith(controlPlaneClient, member1Name, func(_ *clusterv1alpha1.Cluster) bool {
_, err := member1Client.AppsV1().Deployments(deployment.Namespace).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
return err == nil
})
})
ginkgo.It("should apply the configuration and propagate to all member clusters", func() {
// Apply configuration and propagate to all member clusters.
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", deploymentManifest, "--all-clusters")
output, err := cmd.ExecOrDie()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("deployment.apps/%s created", deployment.Name)))
gomega.Expect(output).Should(gomega.MatchRegexp(PropagationPolicyPattern + ` created`))
defer framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
// Extract propagation policy name.
propagationPolicyName, err := extractPropagationPolicyName(output)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
defer framework.RemovePropagationPolicy(karmadaClient, testNamespace, propagationPolicyName)
// Check that the propagation policy is created on the karmada control plane in the given namespace.
framework.WaitPropagationPolicyFitWith(karmadaClient, testNamespace, propagationPolicyName, func(_ *policyv1alpha1.PropagationPolicy) bool {
return true
})
// Check that the deployment is created on the karmada control plane.
framework.WaitDeploymentFitWith(kubeClient, deployment.Namespace, deployment.Name, func(_ *appsv1.Deployment) bool {
return true
})
// Check that the deployment is propagated to all member clusters.
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name, func(_ *appsv1.Deployment) bool {
return true
})
})
ginkgo.It("should run in dry-run mode without making any server requests", func() {
// Apply configuration in dry-run mode.
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", deploymentManifest, "--dry-run=client")
output, err := cmd.ExecOrDie()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
gomega.Expect(output).Should(gomega.ContainSubstring(fmt.Sprintf("deployment.apps/%s", deployment.Name)))
// Check that the deployment is not created on karmada control plane.
gomega.Eventually(func() bool {
_, err = kubeClient.AppsV1().Deployments(deployment.Namespace).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
return apierrors.IsNotFound(err)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.It("should return error for invalid flag", func() {
// Apply configuration with invalid flag.
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", deploymentManifest, "--invalidflag")
_, err := cmd.ExecOrDie()
gomega.Expect(err).Should(gomega.HaveOccurred())
gomega.Expect(strings.Contains(err.Error(), "unknown flag: --invalidflag")).Should(gomega.BeTrue())
})
ginkgo.It("should return error if file does not exist", func() {
// Apply configuration from non-existent file.
nonExistentFile := "/tmp/non-existent.yaml"
cmd := framework.NewKarmadactlCommand(kubeconfig, karmadaContext, karmadactlPath, "", karmadactlTimeout, "apply", "-f", nonExistentFile)
_, err := cmd.ExecOrDie()
gomega.Expect(err).Should(gomega.HaveOccurred())
gomega.Expect(strings.Contains(err.Error(), fmt.Sprintf("error: the path \"%s\" does not exist", nonExistentFile))).Should(gomega.BeTrue())
})
})
// WriteYamlToFile writes the provided object as a YAML file to the specified path.
//
// Parameters:
// - obj: The object to be marshaled to YAML.
// - filePath: The path where the YAML file will be written.
//
// Returns:
// - error: An error if there was an issue during the process, otherwise nil.
func WriteYamlToFile(obj interface{}, filePath string) error {
// Marshal the object to YAML.
yamlData, err := yaml.Marshal(obj)
if err != nil {
return err
}
// Create the file.
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer file.Close()
// Write the YAML data to the file.
_, err = file.Write(yamlData)
if err != nil {
return err
}
return nil
}
// extractPropagationPolicyName extracts the propagation policy name from the input string.
//
// Parameters:
// - input: The string containing the propagation policy information.
//
// Returns:
// - string: The extracted propagation policy name.
// - error: An error if the propagation policy name could not be found.
func extractPropagationPolicyName(input string) (string, error) {
re := regexp.MustCompile(PropagationPolicyPattern)
matches := re.FindStringSubmatch(input)
if len(matches) > 1 {
return matches[1], nil
}
return "", fmt.Errorf("no match found")
}
// extractTokenIDAndSecret extracts the token ID and Secret from the output string.
// It assumes the output format is "tokenID.tokenSecret".
//