diff --git a/Makefile b/Makefile index d821b1739..a76468a8b 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,10 @@ endif endif endif +.PHONY: test-e2e-os +test-e2e-os: + go test -v -run os github.com/kedgeproject/kedge/tests/e2e + # Run all tests .PHONY: test test: test-dep validate test-unit test-unit-cover @@ -127,4 +131,3 @@ vendor-update: .PHONY: test-jsonschema-generation test-jsonschema-generation: docker run -v `pwd`/pkg/spec/types.go:/data/types.go:ro,Z surajd/kedgeschema - diff --git a/scripts/run_e2e.sh b/scripts/run_e2e.sh index 075d8f96a..cad16ba2c 100755 --- a/scripts/run_e2e.sh +++ b/scripts/run_e2e.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -run_command="go test" +run_command="go test -run k8s" while getopts ":p:t:" opt; do case $opt in diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e.go similarity index 56% rename from tests/e2e/e2e_test.go rename to tests/e2e/e2e.go index 8f93d897a..669498737 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e.go @@ -31,7 +31,8 @@ var BinaryLocation = ProjectPath + "kedge" var BinaryCommand = []string{"create", "-n"} const ( - jobTimeout = 10 * time.Minute + jobTimeout = 10 * time.Minute + waitInterval = 5 ) func homeDir() string { @@ -146,8 +147,7 @@ func PodsStarted(t *testing.T, clientset *kubernetes.Clientset, namespace string // Wait for the jobs to complete func waitForJobComplete(clientset *kubernetes.Clientset, namespace string, jobName string) error { - // Interval of 5 - return wait.Poll(5, jobTimeout, func() (bool, error) { + return wait.Poll(waitInterval, jobTimeout, func() (bool, error) { jobStatus, err := clientset.Batch().Jobs(namespace).Get(jobName, metav1.GetOptions{}) if err != nil { return false, errors.Wrap(err, "error getting jobs") @@ -255,192 +255,3 @@ type testData struct { NodePortServices []ServicePort Type string } - -// The "bread and butter" of the test-suite. We will iterate through -// each test that is required and make sure that not only are the pods started -// but that each test is pingable / is accessable. -func Test_Integration(t *testing.T) { - clientset, err := createClient() - if err != nil { - t.Fatalf("error getting kube client: %v", err) - } - - tests := []testData{ - { - TestName: "Testing configMap", - Namespace: "configmap", - InputFiles: []string{ - ProjectPath + "docs/examples/configmap/db.yaml", - ProjectPath + "docs/examples/configmap/web.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Testing customVol", - Namespace: "customvol", - InputFiles: []string{ - ProjectPath + "docs/examples/customVol/db.yaml", - ProjectPath + "docs/examples/customVol/web.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Testing includeResources", - Namespace: "include-resources", - InputFiles: []string{ - ProjectPath + "docs/examples/includeResources/app.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "web", Port: 80}, - }, - }, - { - TestName: "Testing health", - Namespace: "health", - InputFiles: []string{ - ProjectPath + "docs/examples/health/db.yaml", - ProjectPath + "docs/examples/health/web.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Testing healthChecks", - Namespace: "healthchecks", - InputFiles: []string{ - ProjectPath + "docs/examples/healthchecks/db.yaml", - ProjectPath + "docs/examples/healthchecks/web.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Testing secret", - Namespace: "secrets", - InputFiles: []string{ - ProjectPath + "docs/examples/secrets/db.yaml", - ProjectPath + "docs/examples/secrets/web.yaml", - }, - PodStarted: []string{"web"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Testing single file", - Namespace: "singlefile", - InputFiles: []string{ - ProjectPath + "docs/examples/single_file/wordpress.yml", - }, - PodStarted: []string{"wordpress"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 8080}, - }, - }, - { - TestName: "Normal Wordpress test", - Namespace: "wordpress", - InputFiles: []string{ - ProjectPath + "examples/wordpress/wordpress.yaml", - ProjectPath + "examples/wordpress/mariadb.yaml", - }, - PodStarted: []string{"wordpress"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 80}, - }, - }, - { - TestName: "Test portMappings", - Namespace: "portmappings", - InputFiles: []string{ - ProjectPath + "docs/examples/portMappings/wordpress.yaml", - ProjectPath + "docs/examples/portMappings/mariadb.yaml", - }, - PodStarted: []string{"wordpress"}, - NodePortServices: []ServicePort{ - {Name: "wordpress", Port: 80}, - {Name: "mariadb", Port: 3306}, - }, - }, - { - TestName: "Test jobs", - Namespace: "jobs", - InputFiles: []string{ - ProjectPath + "docs/examples/jobs/job.yaml", - }, - PodStarted: []string{"pival"}, - Type: "job", - }, - } - - _, err = clientset.CoreV1().Pods("").List(metav1.ListOptions{}) - if err != nil { - t.Fatalf("Kubernetes cluster is not running or not accessible: %v", err) - } - - for _, test := range tests { - test := test // capture range variable - t.Run(test.TestName, func(t *testing.T) { - t.Parallel() - // create a namespace - _, err := createNS(clientset, test.Namespace) - if err != nil { - t.Fatalf("error creating namespace: %v", err) - } - t.Logf("namespace %q created", test.Namespace) - defer deleteNamespace(t, clientset, test.Namespace) - - // run kedge - convertedOutput, err := RunBinary(test.InputFiles, test.Namespace) - if err != nil { - t.Fatalf("error running kedge: %v", err) - } - t.Log(string(convertedOutput)) - - // see if the pods are running - if err := PodsStarted(t, clientset, test.Namespace, test.PodStarted); err != nil { - t.Fatalf("error finding running pods: %v", err) - } - - if test.Type == "job" { - listJobs, err := clientset.Batch().Jobs(test.Namespace).List(metav1.ListOptions{}) - if err != nil { - t.Fatalf("error getting the job list: %v", err) - } - - for _, job := range listJobs.Items { - err := waitForJobComplete(clientset, test.Namespace, job.Name) - if err != nil { - t.Fatalf("Job failed: %v", err) - } - - t.Logf("Successfully completed the job: %s", job.Name) - } - } else { - - // get endpoints for all services - endPoints, err := getEndPoints(t, clientset, test.Namespace, test.NodePortServices) - if err != nil { - t.Fatalf("error getting nodes: %v", err) - } - - if err := pingEndPoints(t, endPoints); err != nil { - t.Fatalf("error pinging endpoint: %v", err) - } - - t.Logf("Successfully pinged all endpoints!") - } - }) - } -} diff --git a/tests/e2e/e2e_k8s_test.go b/tests/e2e/e2e_k8s_test.go new file mode 100644 index 000000000..c417534e9 --- /dev/null +++ b/tests/e2e/e2e_k8s_test.go @@ -0,0 +1,195 @@ +package e2e + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" +) + +// The "bread and butter" of the test-suite. We will iterate through +// each test that is required and make sure that not only are the pods started +// but that each test is pingable / is accessable. +func Test_k8s_Integration(t *testing.T) { + clientset, err := createClient() + if err != nil { + t.Fatalf("error getting kube client: %v", err) + } + + tests := []testData{ + { + TestName: "Testing configMap", + Namespace: "configmap", + InputFiles: []string{ + ProjectPath + "docs/examples/configmap/db.yaml", + ProjectPath + "docs/examples/configmap/web.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Testing customVol", + Namespace: "customvol", + InputFiles: []string{ + ProjectPath + "docs/examples/customVol/db.yaml", + ProjectPath + "docs/examples/customVol/web.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Testing includeResources", + Namespace: "include-resources", + InputFiles: []string{ + ProjectPath + "docs/examples/includeResources/app.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "web", Port: 80}, + }, + }, + { + TestName: "Testing health", + Namespace: "health", + InputFiles: []string{ + ProjectPath + "docs/examples/health/db.yaml", + ProjectPath + "docs/examples/health/web.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Testing healthChecks", + Namespace: "healthchecks", + InputFiles: []string{ + ProjectPath + "docs/examples/healthchecks/db.yaml", + ProjectPath + "docs/examples/healthchecks/web.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Testing secret", + Namespace: "secrets", + InputFiles: []string{ + ProjectPath + "docs/examples/secrets/db.yaml", + ProjectPath + "docs/examples/secrets/web.yaml", + }, + PodStarted: []string{"web"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Testing single file", + Namespace: "singlefile", + InputFiles: []string{ + ProjectPath + "docs/examples/single_file/wordpress.yml", + }, + PodStarted: []string{"wordpress"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 8080}, + }, + }, + { + TestName: "Normal Wordpress test", + Namespace: "wordpress", + InputFiles: []string{ + ProjectPath + "examples/wordpress/wordpress.yaml", + ProjectPath + "examples/wordpress/mariadb.yaml", + }, + PodStarted: []string{"wordpress"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 80}, + }, + }, + { + TestName: "Test portMappings", + Namespace: "portmappings", + InputFiles: []string{ + ProjectPath + "docs/examples/portMappings/wordpress.yaml", + ProjectPath + "docs/examples/portMappings/mariadb.yaml", + }, + PodStarted: []string{"wordpress"}, + NodePortServices: []ServicePort{ + {Name: "wordpress", Port: 80}, + {Name: "mariadb", Port: 3306}, + }, + }, + { + TestName: "Test jobs", + Namespace: "jobs", + InputFiles: []string{ + ProjectPath + "docs/examples/jobs/job.yaml", + }, + PodStarted: []string{"pival"}, + Type: "job", + }, + } + + _, err = clientset.CoreV1().Pods("").List(metav1.ListOptions{}) + if err != nil { + t.Fatalf("Kubernetes cluster is not running or not accessible: %v", err) + } + + for _, test := range tests { + test := test // capture range variable + t.Run(test.TestName, func(t *testing.T) { + t.Parallel() + // create a namespace + _, err := createNS(clientset, test.Namespace) + if err != nil { + t.Fatalf("error creating namespace: %v", err) + } + t.Logf("namespace %q created", test.Namespace) + defer deleteNamespace(t, clientset, test.Namespace) + + // run kedge + convertedOutput, err := RunBinary(test.InputFiles, test.Namespace) + if err != nil { + t.Fatalf("error running kedge: %v", err) + } + t.Log(string(convertedOutput)) + + // see if the pods are running + if err := PodsStarted(t, clientset, test.Namespace, test.PodStarted); err != nil { + t.Fatalf("error finding running pods: %v", err) + } + + if test.Type == "job" { + listJobs, err := clientset.Batch().Jobs(test.Namespace).List(metav1.ListOptions{}) + if err != nil { + t.Fatalf("error getting the job list: %v", err) + } + + for _, job := range listJobs.Items { + err := waitForJobComplete(clientset, test.Namespace, job.Name) + if err != nil { + t.Fatalf("Job failed: %v", err) + } + + t.Logf("Successfully completed the job: %s", job.Name) + } + } else { + + // get endpoints for all services + endPoints, err := getEndPoints(t, clientset, test.Namespace, test.NodePortServices) + if err != nil { + t.Fatalf("error getting nodes: %v", err) + } + + if err := pingEndPoints(t, endPoints); err != nil { + t.Fatalf("error pinging endpoint: %v", err) + } + + t.Logf("Successfully pinged all endpoints!") + } + }) + } +} diff --git a/tests/e2e/e2e_os_test.go b/tests/e2e/e2e_os_test.go new file mode 100644 index 000000000..dc5555a78 --- /dev/null +++ b/tests/e2e/e2e_os_test.go @@ -0,0 +1,139 @@ +package e2e + +import ( + "bytes" + "fmt" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "os/exec" + "strconv" + "strings" + "testing" +) + +func runCmd(cmdS string) ([]byte, error) { + var cmd *exec.Cmd + var out, stdErr bytes.Buffer + cmd = exec.Command("/bin/sh", "-c", cmdS) + + cmd.Stdout = &out + cmd.Stderr = &stdErr + + err := cmd.Run() + if err != nil { + return nil, fmt.Errorf("error running command %v: %s", cmd, err) + + } + return out.Bytes(), nil +} + +func waitForBuildComplete(namespace string, buildName string) error { + return wait.Poll(waitInterval, jobTimeout, func() (bool, error) { + var buildOut bool + buildStatus, err := runCmd("oc get build --namespace=" + namespace + " --template='{{ range .items }}{{ if (eq .metadata.name \"" + + buildName + "\") }}{{ eq .status.phase \"Complete\" }}{{end}}{{end}}'") + if err != nil { + return false, errors.Wrap(err, "error getting build status") + } + + buildOut, _ = strconv.ParseBool(string(buildStatus)) + return buildOut, nil + }) +} + +// TODO: Use OpenShift client-go API instead of go-template +func Test_os_Integration(t *testing.T) { + + clientset, err := createClient() + if err != nil { + t.Fatalf("error getting kube client: %v", err) + } + + tests := []testData{ + { + TestName: "Testing routes", + Namespace: "testroutes", + InputFiles: []string{ + ProjectPath + "docs/examples/routes/httpd.yml", + }, + PodStarted: []string{"httpd"}, + NodePortServices: []ServicePort{ + {Name: "httpd", Port: 8080}, + }, + }, + + { + TestName: "Testing buildconfig", + Namespace: "buildconfig", + InputFiles: []string{ + ProjectPath + "docs/examples/buildConfigs/ruby-hello-world.yml", + }, + PodStarted: []string{"ruby"}, + Type: "buildconfig", + }, + } + + _, err = clientset.CoreV1().Pods("").List(metav1.ListOptions{}) + if err != nil { + t.Fatalf("Kubernetes cluster is not running or not accessible: %v", err) + } + + for _, test := range tests { + test := test // capture range variable + t.Run(test.TestName, func(t *testing.T) { + t.Parallel() + // create a namespace + _, err := createNS(clientset, test.Namespace) + if err != nil { + t.Fatalf("error creating namespace: %v", err) + } + t.Logf("namespace %q created", test.Namespace) + defer deleteNamespace(t, clientset, test.Namespace) + + // run kedge + convertedOutput, err := RunBinary(test.InputFiles, test.Namespace) + if err != nil { + t.Fatalf("error running kedge: %v", err) + } + t.Log(string(convertedOutput)) + + // see if the pods are running + if err := PodsStarted(t, clientset, test.Namespace, test.PodStarted); err != nil { + t.Fatalf("error finding running pods: %v", err) + } + + if test.Type == "buildconfig" { + listBuilds, err := runCmd("oc get build --template='{{range .items}}{{ .metadata.name }}:{{end}}' | tr \":\" \"\n\"") + if err != nil { + t.Fatalf("error getting the Build list: %v", err) + } + + eachBuild := strings.Split(string(listBuilds), "\n") + for _, build := range eachBuild { + if len(build) > 0 { + err := waitForBuildComplete(test.Namespace, build) + if err != nil { + t.Fatalf("Build failed: %v", err) + } + + t.Logf("Successfully completed the build: %s", build) + } + } + } + + // get endpoints for all services + endPoints, err := getEndPoints(t, clientset, test.Namespace, test.NodePortServices) + if err != nil { + t.Fatalf("error getting nodes: %v", err) + } + + if err := pingEndPoints(t, endPoints); err != nil { + t.Fatalf("error pinging endpoint: %v", err) + } + + t.Logf("Successfully pinged all endpoints!") + + }) + } +}