-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #90 from flacatus/e2e_tests
Add basic tests for cloud shell
- Loading branch information
Showing
10 changed files
with
439 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" | ||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" | ||
_ "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/tests" | ||
"github.com/onsi/ginkgo" | ||
"github.com/onsi/ginkgo/reporters" | ||
"github.com/onsi/gomega" | ||
) | ||
|
||
//Create Constant file | ||
const ( | ||
testResultsDirectory = "/tmp/artifacts" | ||
jUnitOutputFilename = "junit-workspaces-operator.xml" | ||
) | ||
|
||
//SynchronizedBeforeSuite blocks is executed before run all test suites | ||
var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { | ||
//!TODO: Try to create a specific function to call all <ginkgo suite> configuration. | ||
fmt.Println("Starting to setup objects before run ginkgo suite") | ||
config.Namespace = "che-workspace-controller" | ||
|
||
k8sClient, err := client.NewK8sClient() | ||
if err != nil { | ||
fmt.Println("Failed to create workspace client") | ||
panic(err) | ||
} | ||
|
||
controller := deploy.NewDeployment(k8sClient) | ||
|
||
err = controller.CreateNamespace() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
//TODO: Have better improvement of errors. | ||
if err := controller.CreateAllOperatorRoles(); err != nil { | ||
_ = fmt.Errorf("Failed to create roles in clusters %s", err) | ||
} | ||
|
||
if err := controller.CreateOperatorClusterRole(); err != nil { | ||
_ = fmt.Errorf("Failed to create cluster roles in clusters %s", err) | ||
} | ||
|
||
if err := controller.CustomResourceDefinitions(); err != nil { | ||
_ = fmt.Errorf("Failed to add custom resources definitions to cluster %s", err) | ||
} | ||
|
||
if err := controller.DeployWorkspacesController(); err != nil { | ||
_ = fmt.Errorf("Failed to deploy workspace controller %s", err) | ||
} | ||
|
||
return nil | ||
}, func(data []byte) {}) | ||
|
||
var _ = ginkgo.SynchronizedAfterSuite(func() { | ||
k8sClient, err := client.NewK8sClient() | ||
|
||
if err != nil { | ||
_ = fmt.Errorf("Failed to uninstall workspace controller %s", err) | ||
} | ||
|
||
if err = k8sClient.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { | ||
_ = fmt.Errorf("Failed to uninstall workspace controller %s", err) | ||
} | ||
}, func() {}) | ||
|
||
func TestWorkspaceController(t *testing.T) { | ||
gomega.RegisterFailHandler(ginkgo.Fail) | ||
|
||
fmt.Println("Creating ginkgo reporter for Test Harness: Junit and Debug Detail reporter") | ||
var r []ginkgo.Reporter | ||
r = append(r, reporters.NewJUnitReporter(filepath.Join(testResultsDirectory, jUnitOutputFilename))) | ||
|
||
fmt.Println("Running Workspace Controller e2e tests...") | ||
ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "Workspaces Controller Operator Tests", r) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package client | ||
|
||
import ( | ||
"k8s.io/client-go/kubernetes" | ||
"sigs.k8s.io/controller-runtime/pkg/client/config" | ||
) | ||
|
||
type K8sClient struct { | ||
kubeClient *kubernetes.Clientset | ||
} | ||
|
||
// NewK8sClient creates kubernetes client wrapper with helper functions and direct access to k8s go client | ||
func NewK8sClient() (*K8sClient, error) { | ||
cfg, err := config.GetConfig() | ||
if err != nil { | ||
return nil, err | ||
} | ||
client, err := kubernetes.NewForConfig(cfg) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
h := &K8sClient{kubeClient: client} | ||
return h, nil | ||
} | ||
|
||
// Kube returns the clientset for Kubernetes upstream. | ||
func (c *K8sClient) Kube() kubernetes.Interface { | ||
return c.kubeClient | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package client | ||
|
||
import ( | ||
"fmt" | ||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
func (w *K8sClient) OcApply(filePath string) (err error) { | ||
cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", filePath) | ||
output, err := cmd.CombinedOutput() | ||
fmt.Println(string(output)) | ||
if err != nil && !strings.Contains(string(output), "AlreadyExists") { | ||
fmt.Println(err) | ||
} | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package client | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/wait" | ||
) | ||
|
||
func (w *K8sClient) WaitForPodRunningByLabel(label string) (deployed bool, err error) { | ||
timeout := time.After(15 * time.Minute) | ||
tick := time.Tick(1 * time.Second) | ||
|
||
for { | ||
select { | ||
case <-timeout: | ||
return false, errors.New("timed out") | ||
case <-tick: | ||
err := w.WaitForRunningPodBySelector(config.Namespace, label, 3*time.Minute) | ||
if err == nil { | ||
return true, nil | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Wait up to timeout seconds for all pods in 'namespace' with given 'selector' to enter running state. | ||
// Returns an error if no pods are found or not all discovered pods enter running state. | ||
func (w *K8sClient) WaitForRunningPodBySelector(namespace, selector string, timeout time.Duration) error { | ||
podList, err := w.ListPods(namespace, selector) | ||
if err != nil { | ||
return err | ||
} | ||
if len(podList.Items) == 0 { | ||
fmt.Println("Pod not created yet with selector " + selector + " in namespace " + namespace) | ||
|
||
return fmt.Errorf("Pod not created yet in %s with label %s", namespace, selector) | ||
} | ||
|
||
for _, pod := range podList.Items { | ||
fmt.Println("Pod " + pod.Name + " created in namespace " + namespace + "...Checking startup data.") | ||
if err := w.waitForPodRunning(namespace, pod.Name, timeout); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Returns the list of currently scheduled or running pods in `namespace` with the given selector | ||
func (w *K8sClient) ListPods(namespace, selector string) (*v1.PodList, error) { | ||
listOptions := metav1.ListOptions{LabelSelector: selector} | ||
podList, err := w.Kube().CoreV1().Pods(namespace).List(listOptions) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
return podList, nil | ||
} | ||
|
||
// Poll up to timeout seconds for pod to enter running state. | ||
// Returns an error if the pod never enters the running state. | ||
func (w *K8sClient) waitForPodRunning(namespace, podName string, timeout time.Duration) error { | ||
return wait.PollImmediate(time.Second, timeout, w.isPodRunning(podName, namespace)) | ||
} | ||
|
||
// return a condition function that indicates whether the given pod is | ||
// currently running | ||
func (w *K8sClient) isPodRunning(podName, namespace string) wait.ConditionFunc { | ||
return func() (bool, error) { | ||
pod, _ := w.Kube().CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{}) | ||
age := time.Since(pod.GetCreationTimestamp().Time).Seconds() | ||
|
||
switch pod.Status.Phase { | ||
case v1.PodRunning: | ||
fmt.Println("Pod started after", age, "seconds") | ||
return true, nil | ||
case v1.PodFailed, v1.PodSucceeded: | ||
return false, nil | ||
} | ||
return false, nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package config | ||
|
||
var Namespace string |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// | ||
// Copyright (c) 2019-2020 Red Hat, Inc. | ||
// This program and the accompanying materials are made | ||
// available under the terms of the Eclipse Public License 2.0 | ||
// which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 | ||
// | ||
// Contributors: | ||
// Red Hat, Inc. - initial API and implementation | ||
// | ||
|
||
package deploy | ||
|
||
import ( | ||
"fmt" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" | ||
) | ||
|
||
func (w *Deployment) CreateNamespace() error { | ||
_, err := w.kubeClient.Kube().CoreV1().Namespaces().Create(&corev1.Namespace{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: config.Namespace, | ||
}, | ||
}) | ||
return err | ||
} | ||
|
||
func (w *Deployment) DeployWorkspacesController() error { | ||
label := "app=che-workspace-controller" | ||
cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/os") | ||
output, err := cmd.CombinedOutput() | ||
fmt.Println(string(output)) | ||
if err != nil && !strings.Contains(string(output), "AlreadyExists") { | ||
fmt.Println(err) | ||
return err | ||
} | ||
|
||
deploy, err := w.kubeClient.WaitForPodRunningByLabel(label) | ||
if !deploy || err != nil { | ||
fmt.Println("Che Workspaces Controller not deployed") | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (w *Deployment) CreateAllOperatorRoles() error { | ||
cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy") | ||
output, err := cmd.CombinedOutput() | ||
fmt.Println(string(output)) | ||
if err != nil && !strings.Contains(string(output), "AlreadyExists") { | ||
fmt.Println(err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (w *Deployment) CustomResourceDefinitions() error { | ||
cmd := exec.Command("oc", "apply", "-f", "deploy/crds") | ||
output, err := cmd.CombinedOutput() | ||
if err != nil && !strings.Contains(string(output), "AlreadyExists") { | ||
fmt.Println(err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (w *Deployment) CreateOperatorClusterRole() error { | ||
cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/role.yaml") | ||
output, err := cmd.CombinedOutput() | ||
if err != nil && !strings.Contains(string(output), "AlreadyExists") { | ||
fmt.Println(err) | ||
return err | ||
} | ||
return nil | ||
} |
Oops, something went wrong.