Merge pull request #69 from zzxwill/e2e

add e2e framework sample
This commit is contained in:
Sun Jianbo
2020-08-10 17:30:07 +08:00
committed by GitHub
16 changed files with 464 additions and 31 deletions
+24 -5
View File
@@ -34,14 +34,33 @@ jobs:
with:
version: "v0.7.0"
- name: Run Make
run: make
# TODO(zzxwill) This step and the follow one need to be removed after rudr admin:init is ready
- name: Install OAM runtime and prepare WorkloadDefinitions/TraitDefinitions
run: |
sudo apt-get install -y apt-transport-https gnupg2
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get install -y kubectl
- name: Run Make test
run: make test
curl https://helm.baltorepo.com/organization/signing.asc | sudo apt-key add -
sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
kubectl create namespace oam-system
helm repo add crossplane-master https://charts.crossplane.io/master/
helm install oam --namespace oam-system crossplane-master/oam-kubernetes-runtime --devel
kubectl apply -R -f config/samples
- name: Run e2e tests
run: |
make e2e-setup
make e2e-test
make e2e-cleanup
make e2e-cleanup
- name: Run Make
run: make
- name: Run Make test
run: make test
+1
View File
@@ -6,6 +6,7 @@
*.so
*.dylib
bin
e2e/vela
# Test binary, build with `go test -c`
*.test
+43 -3
View File
@@ -9,6 +9,7 @@ contributing to `RudrX` or build a PoC (Proof of Concept).
2. Kubernetes version v1.15+ with `~/.kube/config` configured.
3. OAM Kubernetes Runtime installed.
4. Kustomize version 3.8+
5. ginkgo 1.14.0+ (just for [E2E test](https://github.com/cloud-native-application/RudrX/blob/master/DEVELOPMENT.md#e2e-test))
## Build
* Clone this project
@@ -64,10 +65,49 @@ workloaddefinition.core.oam.dev/deployments.apps deployment
workloaddefinition.core.oam.dev/statefulsets.apps statefulsets.apps
```
## Test
## E2E test
```
$ go test ./pkg/test
ok github.com/cloud-native-application/vela/pkg/test 14.662s
$ make e2e-test
Running Suite: Trait Suite
==========================
Random Seed: 1596559178
Will run 5 of 5 specs
Trait env init
should print env initiation successful message
/Users/zhouzhengxi/Programming/golang/src/github.com/zzxwill/RudrX/e2e/commonContext.go:14
Create env succeed, current env is default
------------------------------
Trait env switch
should show env switch message
/Users/zhouzhengxi/Programming/golang/src/github.com/zzxwill/RudrX/e2e/commonContext.go:40
Switch env succeed, current env is default
------------------------------
Trait run
should print successful creation information
/Users/zhouzhengxi/Programming/golang/src/github.com/zzxwill/RudrX/e2e/commonContext.go:76
Creating AppConfig app-trait-basic
SUCCEED
------------------------------
Trait rudr attach trait
should print successful attached information
/Users/zhouzhengxi/Programming/golang/src/github.com/zzxwill/RudrX/e2e/trait/trait_test.go:24
Applying trait for app
Succeeded!
------------------------------
Trait delete
should print successful deletion information
/Users/zhouzhengxi/Programming/golang/src/github.com/zzxwill/RudrX/e2e/commonContext.go:85
Deleting AppConfig "app-trait-basic"
DELETE SUCCEED
Ran 5 of 5 Specs in 9.717 seconds
SUCCESS! -- 5 Passed | 0 Failed | 0 Pending | 0 Skipped
PASS
```
## Make a pull request
+2 -2
View File
@@ -14,7 +14,7 @@ all: build
# Run tests
test: fmt vet
go test ./... -coverprofile cover.out
go test ./pkg/... -coverprofile cover.out
# Build manager binary
build: fmt vet
@@ -45,7 +45,7 @@ e2e-setup:
e2e-test:
# Run e2e test
go test ./pkg/test
ginkgo -v -r e2e
e2e-cleanup:
# Clean up
+23
View File
@@ -0,0 +1,23 @@
package e2e
import (
"testing"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var rudrPath string
var _ = ginkgo.BeforeSuite(func() {
p, err := e2e.GetCliBinary()
rudrPath = p
gomega.Expect(err).NotTo(gomega.HaveOccurred())
})
func TestApplication(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Application Suite")
}
+33
View File
@@ -0,0 +1,33 @@
package e2e
import (
"fmt"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var (
envName = "env-application"
applicationName = "app-ls-basic"
)
var _ = ginkgo.Describe("Application", func() {
e2e.RefreshContext("refresh")
e2e.EnvInitContext("env init", envName)
e2e.EnvShowContext("env show", envName)
e2e.EnvSwitchContext("env switch", envName)
e2e.WorkloadRunContext("run", fmt.Sprintf("vela containerized:run %s -p 80 --image nginx:1.9.4", applicationName))
ginkgo.Context("ls", func() {
ginkgo.It("should list all applications", func() {
output, err := e2e.Exec("vela app:ls")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("NAME"))
gomega.Expect(output).To(gomega.ContainSubstring(applicationName))
})
})
e2e.WorkloadDeleteContext("delete", applicationName)
})
+44
View File
@@ -0,0 +1,44 @@
package e2e
import (
"os"
"os/exec"
"path"
"strings"
"time"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega/gexec"
)
var (
rudrPath = ""
)
//GetCliBinary is to build rudr binary.
func GetCliBinary() (string, error) {
// TODO(zzxwill) Need to check before building from scratch every time
cwd, _ := os.Getwd()
rudrPath = path.Join(cwd, "..")
mainPath := path.Join(rudrPath, "../cmd/vela/main.go")
cmd := exec.Command("go", "build", "-o", path.Join(rudrPath, "vela"), mainPath)
_, err := cmd.Output()
return rudrPath, err
}
func Exec(cli string) (string, error) {
c := strings.Fields(cli)
commandName := path.Join(rudrPath, c[0])
command := exec.Command(commandName, c[1:]...)
var output []byte
session, err := gexec.Start(command, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
if err != nil {
return string(output), err
}
s := session.Wait(10 * time.Second)
return string(s.Out.Contents()) + string(s.Err.Contents()), nil
}
+105
View File
@@ -0,0 +1,105 @@
package e2e
import (
"fmt"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var (
// Refresh
RefreshContext = func(context string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("Sync commands from your Kubernetes cluster and locally cached them", func() {
output, err := Exec("vela refresh")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("syncing workload definitions from cluster..."))
gomega.Expect(output).To(gomega.ContainSubstring("successfully synced"))
})
})
}
// Env
EnvInitContext = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should print env initiation successful message", func() {
cli := fmt.Sprintf("vela env:init %s --namespace %s", envName, envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("Create env succeed, current env is %s", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
}
EnvShowContext = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should show detailed env message", func() {
cli := fmt.Sprintf("vela env %s", envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("%s\t%s", envName, envName)
gomega.Expect(output).To(gomega.ContainSubstring("NAME"))
gomega.Expect(output).To(gomega.ContainSubstring("NAMESPACE"))
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
}
EnvSwitchContext = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should show env switch message", func() {
cli := fmt.Sprintf("vela env:sw %s", envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("Switch env succeed, current env is %s", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
}
EnvDeleteContext = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should delete all envs", func() {
cli := fmt.Sprintf("vela env:delete %s", envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("%s deleted", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
}
EnvDeleteCurrentUsingContext = func(context string, envName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should delete all envs", func() {
cli := fmt.Sprintf("vela env:delete %s", envName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
expectedOutput := fmt.Sprintf("Error: you can't delete current using env %s", envName)
gomega.Expect(output).To(gomega.ContainSubstring(expectedOutput))
})
})
}
//Workload
WorkloadRunContext = func(context string, cli string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should print successful creation information", func() {
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("SUCCEED"))
})
})
}
WorkloadDeleteContext = func(context string, applicationName string) bool {
return ginkgo.Context(context, func() {
ginkgo.It("should print successful deletion information", func() {
cli := fmt.Sprintf("vela app:delete %s", applicationName)
output, err := Exec(cli)
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("DELETE SUCCEED"))
})
})
}
)
+23
View File
@@ -0,0 +1,23 @@
package e2e
import (
"testing"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var rudrPath string
var _ = ginkgo.BeforeSuite(func() {
p, err := e2e.GetCliBinary()
rudrPath = p
gomega.Expect(err).NotTo(gomega.HaveOccurred())
})
func TestEnv(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Env Suite")
}
+34
View File
@@ -0,0 +1,34 @@
package e2e
import (
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var (
envName = "env-hello"
envName2 = "env-world"
)
var _ = ginkgo.Describe("Env", func() {
e2e.RefreshContext("refresh")
e2e.EnvInitContext("env init", envName)
e2e.EnvInitContext("env init another one", envName2)
e2e.EnvShowContext("env show", envName)
e2e.EnvSwitchContext("env sw", envName)
ginkgo.Context("env list", func() {
ginkgo.It("should list all envs", func() {
output, err := e2e.Exec("vela env")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
gomega.Expect(output).To(gomega.ContainSubstring("NAME"))
gomega.Expect(output).To(gomega.ContainSubstring("NAMESPACE"))
gomega.Expect(output).To(gomega.ContainSubstring(envName))
gomega.Expect(output).To(gomega.ContainSubstring(envName2))
})
})
e2e.EnvDeleteContext("env delete", envName2)
e2e.EnvDeleteCurrentUsingContext("env delete currently using one", envName)
})
+23
View File
@@ -0,0 +1,23 @@
package e2e
import (
"testing"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var rudrPath string
var _ = ginkgo.BeforeSuite(func() {
p, err := e2e.GetCliBinary()
rudrPath = p
gomega.Expect(err).NotTo(gomega.HaveOccurred())
})
func TestEnv(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Trait Suite")
}
+42
View File
@@ -0,0 +1,42 @@
package e2e
import (
"fmt"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
)
var (
envName = "env-trait"
applicationName = "app-trait-basic"
)
var _ = ginkgo.Describe("Trait", func() {
e2e.RefreshContext("refresh")
e2e.EnvInitContext("env init", envName)
e2e.EnvSwitchContext("env switch", envName)
e2e.WorkloadRunContext("run", fmt.Sprintf("vela containerized:run %s -p 80 --image nginx:1.9.4", applicationName))
//ginkgo.Context("vela attach trait", func() {
// ginkgo.It("should print successful attached information", func() {
// cli := fmt.Sprintf("vela manualscaler %s --replicaCount 4", applicationName)
// output, err := e2e.Exec(cli)
// gomega.Expect(err).NotTo(gomega.HaveOccurred())
// gomega.Expect(output).To(gomega.ContainSubstring("Applying trait for app"))
// gomega.Expect(output).To(gomega.ContainSubstring("Succeeded"))
// })
//})
//ginkgo.Context("vela detach trait", func() {
// ginkgo.It("should print successful detached information", func() {
// cli := fmt.Sprintf("vela ManualScaler %s --detach", applicationName)
// output, err := e2e.Exec(cli)
// gomega.Expect(err).NotTo(gomega.HaveOccurred())
// gomega.Expect(output).To(gomega.ContainSubstring("Applying trait for app"))
// gomega.Expect(output).To(gomega.ContainSubstring("Succeeded"))
// })
//})
e2e.WorkloadDeleteContext("delete", applicationName)
})
+23
View File
@@ -0,0 +1,23 @@
package e2e
import (
"testing"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
var rudrPath string
var _ = ginkgo.BeforeSuite(func() {
p, err := e2e.GetCliBinary()
rudrPath = p
gomega.Expect(err).NotTo(gomega.HaveOccurred())
})
func TestWorkload(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
ginkgo.RunSpecs(t, "Workload Suite")
}
+21
View File
@@ -0,0 +1,21 @@
package e2e
import (
"fmt"
"github.com/cloud-native-application/rudrx/e2e"
"github.com/onsi/ginkgo"
)
var (
envName = "env-workload"
applicationName = "app-testworkloadrun-basic"
)
var _ = ginkgo.Describe("Workload", func() {
e2e.RefreshContext("refresh")
e2e.EnvInitContext("env init", envName)
e2e.EnvSwitchContext("env switch", envName)
e2e.WorkloadRunContext("run", fmt.Sprintf("vela containerized:run %s -p 80 --image nginx:1.9.4", applicationName))
e2e.WorkloadDeleteContext("delete", applicationName)
})
+1
View File
@@ -565,6 +565,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY=
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.6.0 h1:IZRgg4sfrDH7nsAD1Y/Nwj+GzIfEwpJSLjCaNC3SbsI=
github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rubenv/sql-migrate v0.0.0-20200212082348-64f95ea68aa3 h1:xkBtI5JktwbW/vf4vopBbhYsRFTGfQWHYXzC0/qYwxI=
+22 -21
View File
@@ -126,29 +126,30 @@ func RetrieveApplicationsByName(ctx context.Context, c client.Client, applicatio
}
for _, a := range applicationList.Items {
componentName := a.Spec.Components[0].ComponentName
component, err := GetComponent(ctx, c, componentName, namespace)
if err != nil {
return applicationMetaList, err
}
var workload corev1alpha2.WorkloadDefinition
if err := json.Unmarshal(component.Spec.Workload.Raw, &workload); err == nil {
workloadName := workload.TypeMeta.Kind
traitNames := GetTraitNamesByApplicationConfiguration(a)
applicationMetaList = append(applicationMetaList, ApplicationMeta{
Name: a.Name,
Workload: workloadName,
Traits: traitNames,
Status: string(a.Status.Conditions[0].Status),
CreatedTime: a.ObjectMeta.CreationTimestamp.String(),
})
for _, com := range a.Spec.Components {
componentName := com.ComponentName
component, err := GetComponent(ctx, c, componentName, namespace)
if err != nil {
return applicationMetaList, err
}
var workload corev1alpha2.WorkloadDefinition
if err := json.Unmarshal(component.Spec.Workload.Raw, &workload); err == nil {
workloadName := workload.TypeMeta.Kind
traitNames := GetTraitNamesByApplicationConfiguration(a)
var status = "UNKNOWN"
if len(a.Status.Conditions) != 0 {
status = string(a.Status.Conditions[0].Status)
}
applicationMetaList = append(applicationMetaList, ApplicationMeta{
Name: a.Name,
Workload: workloadName,
Traits: traitNames,
Status: status,
CreatedTime: a.ObjectMeta.CreationTimestamp.String(),
})
}
}
}
return applicationMetaList, nil
}