Skip to content

Commit

Permalink
e2e: cluster related api and test case. #344 (#466)
Browse files Browse the repository at this point in the history
e2e: MysqlCluster's test case and related api. #344
  • Loading branch information
runkecheng authored Aug 9, 2022
1 parent fa20f80 commit 0304a80
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 66 deletions.
22 changes: 18 additions & 4 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,37 @@ export KUBECONFIG=$HOME/.kube/config
- Running all cases.

```
ginkgo test/e2e/
go test test/e2e/e2e_test.go -test.v
```

- Running all cases labeled `simplecase`.

```
ginkgo --label-filter=simplecase test/e2e/
go test test/e2e/e2e_test.go -test.v --ginkgo.label-filter=simplecase
```

- Skip the cases of describing information contains `Namespace`.

```
ginkgo --skip "list namespace" test/e2e/
go test test/e2e/e2e_test.go -test.v --ginkgo.skip="list namespace"
```

- Just run the description information contains `Namespace`'s cases.

```
ginkgo --focus "list namespace" test/e2e/
go test test/e2e/e2e_test.go -test.v --ginkgo.focus="list namespace"
```

### Supported args

| Args | Default | Description |
| ------------------- | ------------------------------ | ----------------------------------------------------------- |
| kubernetes-host | "" | The kubernetes host, or apiserver, to connect to. |
| kubernetes-config | $KUBECONFIG | Path to config containing embedded authinfo for kubernetes. |
| kubernetes-context | current-context | config context to use for kuberentes. |
| log-dir-prefix | "" | Prefix of the log directory. |
| chart-path | ../../charts/mysql-operator | The chart name or path for mysql operator. |
| operator-image-path | radondb/mysql-operator:v2.2.0 | Image path of mysql operator. |
| sidecar-image-path | radondb/mysql57-sidecar:v2.2.0 | Image full path of mysql sidecar. |
| pod-wait-timeout | 1200 | Timeout to wait for a pod to be ready. |
| dump-logs | false | Dump logs when test case failed. |
117 changes: 117 additions & 0 deletions test/e2e/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
Copyright 2021 RadonDB.
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 cluster

import (
"context"

. "github.com/onsi/ginkgo/v2"
ginkgoTypes "github.com/onsi/ginkgo/v2/types"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/types"

apiv1alpha1 "github.com/radondb/radondb-mysql-kubernetes/api/v1alpha1"
"github.com/radondb/radondb-mysql-kubernetes/test/e2e/framework"
)

var _ = Describe("MySQL Cluster E2E Tests", Label("Cluster"), func() {
var (
f *framework.Framework
cluster *apiv1alpha1.MysqlCluster
clusterKey *types.NamespacedName
two, three, five int32 = 2, 3, 5
)

BeforeEach(func() {
// Init framework.
if f == nil {
By("Init framework")
f = &framework.Framework{
BaseName: "mysqlcluster-e2e",
Log: framework.Log,
}
f.BeforeEach()
}
Expect(f).ShouldNot(BeNil(), "failed to init framework")
})

ReportAfterEach(func(report SpecReport) {
if report.State == ginkgoTypes.SpecStatePassed {
GinkgoWriter.Printf("%s : %s\n", report.LeafNodeText, report.RunTime)
} else {
GinkgoWriter.Printf("%s : %s\n", report.LeafNodeText, report.State)
}
})

// Run the full scale in/out test with label filter: Scale.
// Run only scale out(2 -> 3 -> 5): Scale out.
// Run only scale in(5 -> 3 -> 2): Scale in.
When("Test cluster scale", Label("Scale"), Ordered, func() {
// Init a cluster or get an exist cluster.
BeforeAll(func() {
clusterKey = f.InitOrGetCluster(two)
cluster = &apiv1alpha1.MysqlCluster{}
Expect(f.Client.Get(context.TODO(), *clusterKey, cluster)).To(Succeed(), "failed to get cluster %s", cluster.Name)

By("Testing the cluster readiness")
f.WaitClusterReadiness(clusterKey)
})

Context("Init", Label("Init"), func() {
// BeforeAll will init a cluster or get an exist cluster.
// this container need do no thing and just for record init time.
Specify("Replicas: 0 -> 2", func() {
})
})

Context("Scale out", Label("Scale out"), Ordered, func() {
// Guarantee the initial replicas is 2.
BeforeAll(func() {
f.UpdateClusterReplicas(cluster, two)
f.WaitClusterReadiness(clusterKey)
})

Specify("Replicas: 2 -> 3", func() {
cluster.Spec.Replicas = &three
f.UpdateClusterReplicas(cluster, three)
f.WaitClusterReadiness(clusterKey)
})

Specify("Replicas: 3 -> 5", func() {
f.UpdateClusterReplicas(cluster, five)
f.WaitClusterReadiness(clusterKey)
})
})

Context("Scale in", Label("Scale In"), Ordered, func() {
// Guarantee the initial replicas is 5.
BeforeAll(func() {
f.UpdateClusterReplicas(cluster, five)
f.WaitClusterReadiness(clusterKey)
})

Specify("Replicas: 5 -> 3", func() {
f.UpdateClusterReplicas(cluster, three)
f.WaitClusterReadiness(clusterKey)
})
Specify("Replicas: 3 -> 2", func() {
f.UpdateClusterReplicas(cluster, two)
f.WaitClusterReadiness(clusterKey)
})
})
})
})
55 changes: 14 additions & 41 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ import (
"testing"

. "github.com/onsi/ginkgo/v2"
"github.com/onsi/ginkgo/v2/types"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimeutils "k8s.io/apimachinery/pkg/util/runtime"
clientset "k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -41,6 +39,7 @@ import (

// Test case source.
// Comment out the package that you don't want to run.
_ "github.com/radondb/radondb-mysql-kubernetes/test/e2e/cluster"
_ "github.com/radondb/radondb-mysql-kubernetes/test/e2e/simplecase"
)

Expand Down Expand Up @@ -77,13 +76,13 @@ var _ = SynchronizedBeforeSuite(func() []byte {

if framework.TestContext.DumpLogs {
By("Create log dir")
os.MkdirAll(fmt.Sprintf("%s_%d", framework.TestContext.ReportDirPrefix, GinkgoRandomSeed()), 0777)
os.MkdirAll(fmt.Sprintf("%s_%d", framework.TestContext.LogDirPrefix, GinkgoRandomSeed()), 0777)
}

By("Install RadonDB MySQL Operator")
By("Install operator")
framework.HelmInstallChart(framework.OperatorReleaseName, framework.RadondbMysqlE2eNamespace)
return nil
}, func(data []byte) {
}, func(_ []byte) {
framework.Logf("Running BeforeSuite actions on all node")
})

Expand All @@ -102,7 +101,7 @@ var _ = SynchronizedAfterSuite(func() {
client, err := clientset.NewForConfig(kubeCfg)
Expect(err).NotTo(HaveOccurred())

By("Remove operator release")
By("Remove operator")
framework.HelmPurgeRelease(framework.OperatorReleaseName, framework.RadondbMysqlE2eNamespace)

By("Delete test namespace")
Expand All @@ -115,40 +114,18 @@ var _ = SynchronizedAfterSuite(func() {

var _ = ReportAfterSuite("Collect log", func(report Report) {
if framework.TestContext.DumpLogs {
f, err := os.OpenFile(path.Join(fmt.Sprintf("%s_%d", framework.TestContext.ReportDirPrefix, GinkgoRandomSeed()), "overview.txt"), os.O_RDWR|os.O_CREATE, 0644)
f, err := os.OpenFile(path.Join(fmt.Sprintf("%s_%d", framework.TestContext.LogDirPrefix, GinkgoRandomSeed()), "overview.txt"), os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
fmt.Println(err)
return
}
// Get the kubernetes client.
kubeCfg, err := framework.LoadConfig()
if err != nil {
fmt.Println("Failed to get kubeconfig!")
return
}
client, err := clientset.NewForConfig(kubeCfg)
if err != nil {
fmt.Println("Failed to create k8s client!")
return
}
for _, specReport := range report.SpecReports {
// Collect the summary of all cases.
fmt.Fprintf(f, "%s | %s\n", specReport.FullText(), specReport.State)
// Collect the POD log of failure cases.
if specReport.State.Is(types.SpecStateFailed) {
fileName := fmt.Sprintf("%v.txt", specReport.ContainerHierarchyTexts[len(specReport.ContainerHierarchyTexts)-1])
logFile, err := os.OpenFile(path.Join(fmt.Sprintf("%s_%d", framework.TestContext.ReportDirPrefix, GinkgoRandomSeed()), fileName), os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
fmt.Printf("Failed to open file: %s with error: %s\n", fileName, err)
continue
}
fmt.Fprintf(logFile, "## Start test: %v\n", specReport.ContainerHierarchyTexts)

framework.LogPodsWithLabels(client, framework.RadondbMysqlE2eNamespace, nil, time.Since(specReport.EndTime.Add(-1*time.Minute)), logFile)

fmt.Fprintf(logFile, "## END test\n")
logFile.Close()

if specReport.FullText() != "" {
// Collect the summary of all cases.
fmt.Fprintf(f, "%s | %s | %v\n", specReport.FullText(), specReport.State, specReport.RunTime)
}
// TODO: Collect the POD log of failure cases.
}
f.Close()
}
Expand All @@ -160,8 +137,6 @@ var _ = ReportAfterSuite("Collect log", func(report Report) {
// generated in this directory, and cluster logs will also be saved.
// This function is called on each Ginkgo node in parallel mode.
func RunE2ETests(t *testing.T) {
runtimeutils.ReallyCrash = true

RegisterFailHandler(ginkgowrapper.Fail)

// Fetch the current config.
Expand All @@ -170,15 +145,13 @@ func RunE2ETests(t *testing.T) {
reporterConfig.FullTrace = true
// Whether printing more detail.
reporterConfig.Verbose = true
// Whether to display information of GinkgoWriter.
reporterConfig.AlwaysEmitGinkgoWriter = true
if framework.TestContext.DumpLogs {
if framework.TestContext.ReportDirPrefix == "" {
if framework.TestContext.LogDirPrefix == "" {
now := time.Now()
framework.TestContext.ReportDirPrefix = fmt.Sprintf("logs_%d%d_%d%d", now.Month(), now.Day(), now.Hour(), now.Minute())
framework.TestContext.LogDirPrefix = fmt.Sprintf("logs_%d%d_%d%d", now.Month(), now.Day(), now.Hour(), now.Minute())
}
// Path of JUnitReport.
reporterConfig.JUnitReport = path.Join(fmt.Sprintf("%s_%d", framework.TestContext.ReportDirPrefix, GinkgoRandomSeed()), "junit.xml")
reporterConfig.JUnitReport = path.Join(fmt.Sprintf("%s_%d", framework.TestContext.LogDirPrefix, GinkgoRandomSeed()), "junit.xml")
}

RunSpecs(t, "MySQL Operator E2E Suite", Label("MySQL Operator"), suiteConfig, reporterConfig)
Expand Down
Loading

0 comments on commit 0304a80

Please sign in to comment.