From b03d97781a3e897e755ff7d035f4ba2708d6187b Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 09:25:12 +0200 Subject: [PATCH 01/11] Add basic tests for cloud shell Signed-off-by: flacatus --- go.mod | 2 + test/e2e/cmd/workspaces_test.go | 102 ++++++++++++++++++++++++ test/e2e/pkg/metadata/metadata.go | 7 ++ test/e2e/pkg/tests/cloud_shell_tests.go | 22 +++++ test/e2e/pkg/workspaces/client.go | 24 ++++++ test/e2e/pkg/workspaces/deserialize.go | 48 +++++++++++ test/e2e/pkg/workspaces/oc.go | 76 ++++++++++++++++++ test/e2e/pkg/workspaces/util.go | 89 +++++++++++++++++++++ test/e2e/pkg/workspaces/workspaces.go | 42 ++++++++++ 9 files changed, 412 insertions(+) create mode 100644 test/e2e/cmd/workspaces_test.go create mode 100644 test/e2e/pkg/metadata/metadata.go create mode 100644 test/e2e/pkg/tests/cloud_shell_tests.go create mode 100644 test/e2e/pkg/workspaces/client.go create mode 100644 test/e2e/pkg/workspaces/deserialize.go create mode 100644 test/e2e/pkg/workspaces/oc.go create mode 100644 test/e2e/pkg/workspaces/util.go create mode 100644 test/e2e/pkg/workspaces/workspaces.go diff --git a/go.mod b/go.mod index 173b23219..0837a68df 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,8 @@ require ( ) require ( + github.com/onsi/ginkgo v1.11.0 + github.com/onsi/gomega v1.8.1 github.com/operator-framework/operator-sdk v0.17.0 github.com/spf13/pflag v1.0.5 k8s.io/api v0.17.4 diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go new file mode 100644 index 000000000..ec680367f --- /dev/null +++ b/test/e2e/cmd/workspaces_test.go @@ -0,0 +1,102 @@ +package cmd + +import ( + "fmt" + "path/filepath" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" + _ "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/tests" + workspaces "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/workspaces" + "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 configuration. + fmt.Println("Starting to setup objects before run ginkgo suite") + metadata.Namespace.Name = "che-workspace-controller" + + workspaces := workspaces.NewWorkspaceClient() + + ns := newNamespace() + ns, err := workspaces.Kube().CoreV1().Namespaces().Create(ns) + + if err != nil { + fmt.Println("Failed to create namespace") + } + + if err := workspaces.CreatePluginRegistryDeployment(); err != nil { + _ = fmt.Errorf("Failed to create deployment for plugin registry") + } + + if err := workspaces.CreatePluginRegistryService(); err != nil { + _ = fmt.Errorf("Failed to create plugin registry service %s", err) + } + + if err := workspaces.CreateOpenshiftRoute(); err != nil { + _ = fmt.Errorf("Failed to create route in cluster %s", err) + } + + if err := workspaces.CreateAllOperatorRoles(); err != nil { + _ = fmt.Errorf("Failed to create roles in clusters %s", err) + } + + if err := workspaces.CreateOperatorClusterRole(); err != nil { + _ = fmt.Errorf("Failed to create roles in clusters %s", err) + } + + if err := workspaces.CustomResourceDefinitions(); err != nil { + _ = fmt.Errorf("Failed to add custom resources definitions to cluster %s", err) + } + + if err := workspaces.DeployWorkspacesController(); err != nil { + _ = fmt.Errorf("Failed to deploy workspace controller %s", err) + } + + return nil +}, func(data []byte) {}) + +var _ = ginkgo.SynchronizedAfterSuite(func() { + workspaces := workspaces.NewWorkspaceClient() + + if err := workspaces.Kube().CoreV1().Namespaces().Delete(metadata.Namespace.Name, &metav1.DeleteOptions{}); err != nil { + _ = fmt.Errorf("Failed to deploy workspace controller %s", err) + } +}, func() {}) + +func TestHarnessCodeReadyWorkspaces(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) + +} + +func newNamespace() (ns *corev1.Namespace) { + return &corev1.Namespace{ + + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.Version, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: metadata.Namespace.Name, + }, + } +} diff --git a/test/e2e/pkg/metadata/metadata.go b/test/e2e/pkg/metadata/metadata.go new file mode 100644 index 000000000..b9269f077 --- /dev/null +++ b/test/e2e/pkg/metadata/metadata.go @@ -0,0 +1,7 @@ +package metadata + +type OperatorNamespace struct { + Name string +} + +var Namespace = OperatorNamespace{} diff --git a/test/e2e/pkg/tests/cloud_shell_tests.go b/test/e2e/pkg/tests/cloud_shell_tests.go new file mode 100644 index 000000000..099ff89f6 --- /dev/null +++ b/test/e2e/pkg/tests/cloud_shell_tests.go @@ -0,0 +1,22 @@ +package tests + +import ( + "fmt" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/workspaces" + "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) +var client workspaces.CodeReady + +var _ = ginkgo.Describe("[Create Cloud Shell Workspace]", func() { + ginkgo.It("Add cloud shell to cluster", func() { + label := "che.workspace_name=cloud-shell" + workspace := workspaces.NewWorkspaceClient() + _ = workspace.AddCloudShellSample() + deploy , err := client.PodDeployWaitUtil(label) + if !deploy { + fmt.Println("Cloud Shell not deployed") + } + Expect(err).NotTo(HaveOccurred()) + }) +}) diff --git a/test/e2e/pkg/workspaces/client.go b/test/e2e/pkg/workspaces/client.go new file mode 100644 index 000000000..eec99f157 --- /dev/null +++ b/test/e2e/pkg/workspaces/client.go @@ -0,0 +1,24 @@ +package workspaces + +import ( + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client/config" +) + +type CodeReady struct { + rest *rest.Config +} + +// NewCodeReady creates C, a workspaces used to expose common testing functions. +func NewWorkspaceClient() *CodeReady { + h := &CodeReady{} + return h +} + +// Kube returns the clientset for Kubernetes upstream. +func (c *CodeReady) Kube() kubernetes.Interface { + cfg, _ := config.GetConfig() + client, _ := kubernetes.NewForConfig(cfg) + return client +} diff --git a/test/e2e/pkg/workspaces/deserialize.go b/test/e2e/pkg/workspaces/deserialize.go new file mode 100644 index 000000000..5c8cd5c78 --- /dev/null +++ b/test/e2e/pkg/workspaces/deserialize.go @@ -0,0 +1,48 @@ +package workspaces + +import ( + "fmt" + "io/ioutil" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" +) + +func deserializePluginRegistryDeployment() (pluginRegistry *appsv1.Deployment, err error) { + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + } + file, err := ioutil.ReadFile("deploy/registry/local/deployment.yaml") + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + } + deployment := string(file) + decode := scheme.Codecs.UniversalDeserializer().Decode + object, _, err := decode([]byte(deployment), nil, nil) + if err != nil { + fmt.Println("Failed to deserialize yaml %s", err) + return nil, err + } + pluginRegistry = object.(*appsv1.Deployment) + return pluginRegistry, nil +} + +func deserializePluginRegistryService() (pluginRegistry *corev1.Service, err error) { + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + } + file, err := ioutil.ReadFile("deploy/registry/local/service.yaml") + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + } + deployment := string(file) + decode := scheme.Codecs.UniversalDeserializer().Decode + object, _, err := decode([]byte(deployment), nil, nil) + if err != nil { + fmt.Println("Failed to deserialize yaml %s", err) + return nil, err + } + pluginRegistry = object.(*corev1.Service) + return pluginRegistry, nil +} diff --git a/test/e2e/pkg/workspaces/oc.go b/test/e2e/pkg/workspaces/oc.go new file mode 100644 index 000000000..8f979cf8a --- /dev/null +++ b/test/e2e/pkg/workspaces/oc.go @@ -0,0 +1,76 @@ +package workspaces + +import ( + "fmt" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" + "os/exec" + "strings" +) + +func (w *CodeReady) DeployWorkspacesController() (err error) { + label := "app=che-workspace-controller" + cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-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.PodDeployWaitUtil(label) + if !deploy { + fmt.Println("Che Workspaces Controller not deployed") + return err + } + return err +} + +func (w *CodeReady) CreateAllOperatorRoles() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy") + output, err := cmd.CombinedOutput() + fmt.Println(string(output)) + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *CodeReady) CreateOpenshiftRoute() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/registry/local/os") + output, err := cmd.CombinedOutput() + fmt.Println(string(output)) + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *CodeReady) CustomResourceDefinitions() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/crds") + output, err := cmd.CombinedOutput() + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *CodeReady) CreateOperatorClusterRole() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/role.yaml") + output, err := cmd.CombinedOutput() + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *CodeReady) AddCloudShellSample() (err error) { + const namespace = "che-workspace-controller" + cmd := exec.Command("oc", "apply", "--namespace", namespace, "-f", "samples/cloud-shell.yaml") + output, err := cmd.CombinedOutput() + fmt.Println(string(output)) + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + diff --git a/test/e2e/pkg/workspaces/util.go b/test/e2e/pkg/workspaces/util.go new file mode 100644 index 000000000..99bb9a1f9 --- /dev/null +++ b/test/e2e/pkg/workspaces/util.go @@ -0,0 +1,89 @@ +package workspaces + +import ( + "errors" + "fmt" + "time" + + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +func (w *CodeReady) PodDeployWaitUtil(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: + desc := w.WaitForPodBySelectorRunning(metadata.Namespace.Name, label, 180) + if desc != nil { + } else { + return true, nil + } + } + } +} + +// return a condition function that indicates whether the given pod is +// currently running +func (w *CodeReady) 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 + } +} + +// Poll up to timeout seconds for pod to enter running state. +// Returns an error if the pod never enters the running state. +func (w *CodeReady) waitForPodRunning(namespace, podName string, timeout time.Duration) error { + return wait.PollImmediate(time.Second, timeout, w.isPodRunning(podName, namespace)) +} + +// Returns the list of currently scheduled or running pods in `namespace` with the given selector +func (w *CodeReady) 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 +} + +// 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 *CodeReady) WaitForPodBySelectorRunning(namespace, selector string, timeout int) 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, time.Duration(timeout)*time.Second); err != nil { + return err + } + } + + return nil +} diff --git a/test/e2e/pkg/workspaces/workspaces.go b/test/e2e/pkg/workspaces/workspaces.go new file mode 100644 index 000000000..11d8c6003 --- /dev/null +++ b/test/e2e/pkg/workspaces/workspaces.go @@ -0,0 +1,42 @@ +package workspaces + +import ( + "fmt" + + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" +) + +func (w *CodeReady) CreatePluginRegistryDeployment() (err error) { + label := "app=che-plugin-registry" + deployment, err := deserializePluginRegistryDeployment() + + if err != nil { + fmt.Println("Failed to deserialize deployment") + return err + } + + deployment, err = w.Kube().AppsV1().Deployments(metadata.Namespace.Name).Create(deployment) + + if err != nil { + fmt.Println("Failed to create deployment %s: %s", deployment.Name, err) + return err + } + + deploy, err := w.PodDeployWaitUtil(label) + if !deploy { + fmt.Println("Che Workspaces Controller not deployed") + return err + } + return nil +} + +func (w *CodeReady) CreatePluginRegistryService() (err error) { + deserializeService, _ := deserializePluginRegistryService() + + service, err := w.Kube().CoreV1().Services(metadata.Namespace.Name).Create(deserializeService) + if err != nil { + fmt.Println("Failed to create deployment %s: %s", service.Name, err) + return err + } + return nil +} From a39ecc12b5ba3bc8b6dd8938a43ad302c5ac1f82 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 20:49:47 +0200 Subject: [PATCH 02/11] Delete unnecessary code and add improvements Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 58 ++++++++------ test/e2e/pkg/client/client.go | 42 ++++++++++ test/e2e/pkg/client/oc.go | 30 +++++++ test/e2e/pkg/client/pod.go | 101 ++++++++++++++++++++++++ test/e2e/pkg/config/config.go | 15 ++++ test/e2e/pkg/deploy/controller.go | 76 ++++++++++++++++++ test/e2e/pkg/deploy/deploy.go | 25 ++++++ test/e2e/pkg/deploy/deserialize.go | 56 +++++++++++++ test/e2e/pkg/deploy/plugin_registry.go | 53 +++++++++++++ test/e2e/pkg/tests/cloud_shell_tests.go | 33 ++++++-- test/e2e/pkg/workspaces/client.go | 24 ------ test/e2e/pkg/workspaces/oc.go | 76 ------------------ test/e2e/pkg/workspaces/workspaces.go | 42 ---------- 13 files changed, 457 insertions(+), 174 deletions(-) create mode 100644 test/e2e/pkg/client/client.go create mode 100644 test/e2e/pkg/client/oc.go create mode 100644 test/e2e/pkg/client/pod.go create mode 100644 test/e2e/pkg/config/config.go create mode 100644 test/e2e/pkg/deploy/controller.go create mode 100644 test/e2e/pkg/deploy/deploy.go create mode 100644 test/e2e/pkg/deploy/deserialize.go create mode 100644 test/e2e/pkg/deploy/plugin_registry.go delete mode 100644 test/e2e/pkg/workspaces/client.go delete mode 100644 test/e2e/pkg/workspaces/oc.go delete mode 100644 test/e2e/pkg/workspaces/workspaces.go diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index ec680367f..c53aadda0 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -1,16 +1,29 @@ +// +// 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" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" + deploy2 "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" "path/filepath" "testing" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" _ "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/tests" - workspaces "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/workspaces" + workspaces "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" "github.com/onsi/ginkgo" "github.com/onsi/ginkgo/reporters" "github.com/onsi/gomega" @@ -26,42 +39,35 @@ const ( var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { //!TODO: Try to create a specific function to call all configuration. fmt.Println("Starting to setup objects before run ginkgo suite") - metadata.Namespace.Name = "che-workspace-controller" + config.Namespace = "che-workspace-controller" - workspaces := workspaces.NewWorkspaceClient() + workspaces, err := workspaces.NewK8sClient() + if err != nil { + fmt.Println("Failed to create workspace client") + } ns := newNamespace() - ns, err := workspaces.Kube().CoreV1().Namespaces().Create(ns) + ns, err = workspaces.Kube().CoreV1().Namespaces().Create(ns) if err != nil { fmt.Println("Failed to create namespace") } - if err := workspaces.CreatePluginRegistryDeployment(); err != nil { - _ = fmt.Errorf("Failed to create deployment for plugin registry") - } + deploy := deploy2.NewDeployment(workspaces) - if err := workspaces.CreatePluginRegistryService(); err != nil { - _ = fmt.Errorf("Failed to create plugin registry service %s", err) - } - - if err := workspaces.CreateOpenshiftRoute(); err != nil { - _ = fmt.Errorf("Failed to create route in cluster %s", err) - } - - if err := workspaces.CreateAllOperatorRoles(); err != nil { + if err := deploy.CreateAllOperatorRoles(); err != nil { _ = fmt.Errorf("Failed to create roles in clusters %s", err) } - if err := workspaces.CreateOperatorClusterRole(); err != nil { + if err := deploy.CreateOperatorClusterRole(); err != nil { _ = fmt.Errorf("Failed to create roles in clusters %s", err) } - if err := workspaces.CustomResourceDefinitions(); err != nil { + if err := deploy.CustomResourceDefinitions(); err != nil { _ = fmt.Errorf("Failed to add custom resources definitions to cluster %s", err) } - if err := workspaces.DeployWorkspacesController(); err != nil { + if err := deploy.DeployWorkspacesController(); err != nil { _ = fmt.Errorf("Failed to deploy workspace controller %s", err) } @@ -69,13 +75,18 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { }, func(data []byte) {}) var _ = ginkgo.SynchronizedAfterSuite(func() { - workspaces := workspaces.NewWorkspaceClient() + workspaces, err := workspaces.NewK8sClient() + + if err != nil { + _ = fmt.Errorf("Failed to create workspace client to uninstall controller %s", err) + } - if err := workspaces.Kube().CoreV1().Namespaces().Delete(metadata.Namespace.Name, &metav1.DeleteOptions{}); err != nil { + if err = workspaces.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { _ = fmt.Errorf("Failed to deploy workspace controller %s", err) } }, func() {}) + func TestHarnessCodeReadyWorkspaces(t *testing.T) { gomega.RegisterFailHandler(ginkgo.Fail) @@ -90,13 +101,12 @@ func TestHarnessCodeReadyWorkspaces(t *testing.T) { func newNamespace() (ns *corev1.Namespace) { return &corev1.Namespace{ - TypeMeta: metav1.TypeMeta{ Kind: "Namespace", APIVersion: corev1.SchemeGroupVersion.Version, }, ObjectMeta: metav1.ObjectMeta{ - Name: metadata.Namespace.Name, + Name: config.Namespace, }, } } diff --git a/test/e2e/pkg/client/client.go b/test/e2e/pkg/client/client.go new file mode 100644 index 000000000..d373916d9 --- /dev/null +++ b/test/e2e/pkg/client/client.go @@ -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 +} + +// NewCodeReady creates C, a workspaces used to expose common testing functions. +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 +} diff --git a/test/e2e/pkg/client/oc.go b/test/e2e/pkg/client/oc.go new file mode 100644 index 000000000..73e3bd204 --- /dev/null +++ b/test/e2e/pkg/client/oc.go @@ -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" + "os/exec" + "strings" +) + +func (w *K8sClient) OcApply(filePath string) (err error) { + const namespace = "che-workspace-controller" + cmd := exec.Command("oc", "apply", "--namespace", namespace, "-f", filePath) + output, err := cmd.CombinedOutput() + fmt.Println(string(output)) + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} diff --git a/test/e2e/pkg/client/pod.go b/test/e2e/pkg/client/pod.go new file mode 100644 index 000000000..ca91cabe6 --- /dev/null +++ b/test/e2e/pkg/client/pod.go @@ -0,0 +1,101 @@ +// +// 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" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" + "time" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +func (w *K8sClient) PodDeployWaitUtil(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: + desc := w.WaitForPodBySelectorRunning(config.Namespace, label, 180) + if desc != nil { + } else { + return true, nil + } + } + } +} + +// 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 + } +} + +// 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)) +} + +// 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 +} + +// 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) WaitForPodBySelectorRunning(namespace, selector string, timeout int) 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, time.Duration(timeout)*time.Second); err != nil { + return err + } + } + + return nil +} diff --git a/test/e2e/pkg/config/config.go b/test/e2e/pkg/config/config.go new file mode 100644 index 000000000..c4edc3ab1 --- /dev/null +++ b/test/e2e/pkg/config/config.go @@ -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 diff --git a/test/e2e/pkg/deploy/controller.go b/test/e2e/pkg/deploy/controller.go new file mode 100644 index 000000000..3c334d3ed --- /dev/null +++ b/test/e2e/pkg/deploy/controller.go @@ -0,0 +1,76 @@ +// +// 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" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" + "os/exec" + "strings" +) + +func (w *Deployment) DeployWorkspacesController() (err 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.PodDeployWaitUtil(label) + if !deploy { + fmt.Println("Che Workspaces Controller not deployed") + return err + } + return err +} + +func (w *Deployment) CreateAllOperatorRoles() (err 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 +} + +func (w *Deployment) CreatePluginRegistryRoute() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/registry/local/os") + output, err := cmd.CombinedOutput() + fmt.Println(string(output)) + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *Deployment) CustomResourceDefinitions() (err error) { + cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/crds") + output, err := cmd.CombinedOutput() + if err != nil && !strings.Contains(string(output), "AlreadyExists") { + fmt.Println(err) + } + return err +} + +func (w *Deployment) CreateOperatorClusterRole() (err 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 +} diff --git a/test/e2e/pkg/deploy/deploy.go b/test/e2e/pkg/deploy/deploy.go new file mode 100644 index 000000000..b261c7197 --- /dev/null +++ b/test/e2e/pkg/deploy/deploy.go @@ -0,0 +1,25 @@ +// +// 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 ( + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" +) + +type Deployment struct { + kubeClient *client.K8sClient +} + +func NewDeployment(kubeClient *client.K8sClient) *Deployment { + return &Deployment{kubeClient: kubeClient} +} diff --git a/test/e2e/pkg/deploy/deserialize.go b/test/e2e/pkg/deploy/deserialize.go new file mode 100644 index 000000000..ac7b62c70 --- /dev/null +++ b/test/e2e/pkg/deploy/deserialize.go @@ -0,0 +1,56 @@ +// +// 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" + "io/ioutil" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" +) + +func deserializePluginRegistryDeployment() (pluginRegistry *appsv1.Deployment, err error) { + file, err := ioutil.ReadFile("deploy/registry/local/deployment.yaml") + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + return nil, err + } + deployment := string(file) + decode := scheme.Codecs.UniversalDeserializer().Decode + object, _, err := decode([]byte(deployment), nil, nil) + if err != nil { + fmt.Println("Failed to deserialize yaml %s", err) + return nil, err + } + pluginRegistry = object.(*appsv1.Deployment) + return pluginRegistry, nil +} + +func deserializePluginRegistryService() (pluginRegistry *corev1.Service, err error) { + file, err := ioutil.ReadFile("deploy/registry/local/service.yaml") + if err != nil { + fmt.Println("Failed to locate operator deployment yaml, %s", err) + return nil, err + } + deployment := string(file) + decode := scheme.Codecs.UniversalDeserializer().Decode + object, _, err := decode([]byte(deployment), nil, nil) + if err != nil { + fmt.Println("Failed to deserialize yaml %s", err) + return nil, err + } + pluginRegistry = object.(*corev1.Service) + return pluginRegistry, nil +} diff --git a/test/e2e/pkg/deploy/plugin_registry.go b/test/e2e/pkg/deploy/plugin_registry.go new file mode 100644 index 000000000..9ca633a93 --- /dev/null +++ b/test/e2e/pkg/deploy/plugin_registry.go @@ -0,0 +1,53 @@ +// +// 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" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" +) + +func (w *Deployment) CreatePluginRegistryDeployment() (err error) { + label := "app=che-plugin-registry" + deployment, err := deserializePluginRegistryDeployment() + + if err != nil { + fmt.Println("Failed to deserialize deployment") + return err + } + + deployment, err = w.kubeClient.Kube().AppsV1().Deployments(config.Namespace).Create(deployment) + + if err != nil { + fmt.Println("Failed to create deployment %s: %s", deployment.Name, err) + return err + } + + deploy, err := w.kubeClient.PodDeployWaitUtil(label) + if !deploy { + fmt.Println("Che Workspaces Controller not deployed") + return err + } + return nil +} + +func (w *Deployment) CreatePluginRegistryService() (err error) { + deserializeService, _ := deserializePluginRegistryService() + + _, err = w.kubeClient.Kube().CoreV1().Services(config.Namespace).Create(deserializeService) + if err != nil { + fmt.Println("Failed to create service %s: %s", deserializeService.Name, err) + return err + } + return nil +} diff --git a/test/e2e/pkg/tests/cloud_shell_tests.go b/test/e2e/pkg/tests/cloud_shell_tests.go index 099ff89f6..29f73129a 100644 --- a/test/e2e/pkg/tests/cloud_shell_tests.go +++ b/test/e2e/pkg/tests/cloud_shell_tests.go @@ -1,22 +1,39 @@ +// +// 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 tests import ( "fmt" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/workspaces" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" + "github.com/onsi/gomega" ) -var client workspaces.CodeReady var _ = ginkgo.Describe("[Create Cloud Shell Workspace]", func() { ginkgo.It("Add cloud shell to cluster", func() { label := "che.workspace_name=cloud-shell" - workspace := workspaces.NewWorkspaceClient() - _ = workspace.AddCloudShellSample() - deploy , err := client.PodDeployWaitUtil(label) + k8sClient, err := client.NewK8sClient() + if err != nil { + //TODO make sure it's the right way to fail here + ginkgo.Fail("Failed to create k8s client: " + err.Error()) + return + } + _ = k8sClient.OcApply("samples/cloud-shell.yaml") + deploy, err := k8sClient.PodDeployWaitUtil(label) + if !deploy { fmt.Println("Cloud Shell not deployed") } - Expect(err).NotTo(HaveOccurred()) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) }) -}) +}) \ No newline at end of file diff --git a/test/e2e/pkg/workspaces/client.go b/test/e2e/pkg/workspaces/client.go deleted file mode 100644 index eec99f157..000000000 --- a/test/e2e/pkg/workspaces/client.go +++ /dev/null @@ -1,24 +0,0 @@ -package workspaces - -import ( - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client/config" -) - -type CodeReady struct { - rest *rest.Config -} - -// NewCodeReady creates C, a workspaces used to expose common testing functions. -func NewWorkspaceClient() *CodeReady { - h := &CodeReady{} - return h -} - -// Kube returns the clientset for Kubernetes upstream. -func (c *CodeReady) Kube() kubernetes.Interface { - cfg, _ := config.GetConfig() - client, _ := kubernetes.NewForConfig(cfg) - return client -} diff --git a/test/e2e/pkg/workspaces/oc.go b/test/e2e/pkg/workspaces/oc.go deleted file mode 100644 index 8f979cf8a..000000000 --- a/test/e2e/pkg/workspaces/oc.go +++ /dev/null @@ -1,76 +0,0 @@ -package workspaces - -import ( - "fmt" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" - "os/exec" - "strings" -) - -func (w *CodeReady) DeployWorkspacesController() (err error) { - label := "app=che-workspace-controller" - cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-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.PodDeployWaitUtil(label) - if !deploy { - fmt.Println("Che Workspaces Controller not deployed") - return err - } - return err -} - -func (w *CodeReady) CreateAllOperatorRoles() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy") - output, err := cmd.CombinedOutput() - fmt.Println(string(output)) - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - -func (w *CodeReady) CreateOpenshiftRoute() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/registry/local/os") - output, err := cmd.CombinedOutput() - fmt.Println(string(output)) - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - -func (w *CodeReady) CustomResourceDefinitions() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/crds") - output, err := cmd.CombinedOutput() - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - -func (w *CodeReady) CreateOperatorClusterRole() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", metadata.Namespace.Name, "-f", "deploy/role.yaml") - output, err := cmd.CombinedOutput() - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - -func (w *CodeReady) AddCloudShellSample() (err error) { - const namespace = "che-workspace-controller" - cmd := exec.Command("oc", "apply", "--namespace", namespace, "-f", "samples/cloud-shell.yaml") - output, err := cmd.CombinedOutput() - fmt.Println(string(output)) - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - diff --git a/test/e2e/pkg/workspaces/workspaces.go b/test/e2e/pkg/workspaces/workspaces.go deleted file mode 100644 index 11d8c6003..000000000 --- a/test/e2e/pkg/workspaces/workspaces.go +++ /dev/null @@ -1,42 +0,0 @@ -package workspaces - -import ( - "fmt" - - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" -) - -func (w *CodeReady) CreatePluginRegistryDeployment() (err error) { - label := "app=che-plugin-registry" - deployment, err := deserializePluginRegistryDeployment() - - if err != nil { - fmt.Println("Failed to deserialize deployment") - return err - } - - deployment, err = w.Kube().AppsV1().Deployments(metadata.Namespace.Name).Create(deployment) - - if err != nil { - fmt.Println("Failed to create deployment %s: %s", deployment.Name, err) - return err - } - - deploy, err := w.PodDeployWaitUtil(label) - if !deploy { - fmt.Println("Che Workspaces Controller not deployed") - return err - } - return nil -} - -func (w *CodeReady) CreatePluginRegistryService() (err error) { - deserializeService, _ := deserializePluginRegistryService() - - service, err := w.Kube().CoreV1().Services(metadata.Namespace.Name).Create(deserializeService) - if err != nil { - fmt.Println("Failed to create deployment %s: %s", service.Name, err) - return err - } - return nil -} From 7a327d0106c5e856e3c81ca91f6b30ab73511eae Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 21:01:14 +0200 Subject: [PATCH 03/11] Fix tests name Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 4 +- test/e2e/pkg/client/pod.go | 3 +- test/e2e/pkg/deploy/deserialize.go | 56 -------------------------- test/e2e/pkg/deploy/plugin_registry.go | 53 ------------------------ 4 files changed, 3 insertions(+), 113 deletions(-) delete mode 100644 test/e2e/pkg/deploy/deserialize.go delete mode 100644 test/e2e/pkg/deploy/plugin_registry.go diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index c53aadda0..f5d7b30a8 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -78,7 +78,7 @@ var _ = ginkgo.SynchronizedAfterSuite(func() { workspaces, err := workspaces.NewK8sClient() if err != nil { - _ = fmt.Errorf("Failed to create workspace client to uninstall controller %s", err) + _ = fmt.Errorf("Failed to uninstall workspace controller %s", err) } if err = workspaces.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { @@ -87,7 +87,7 @@ var _ = ginkgo.SynchronizedAfterSuite(func() { }, func() {}) -func TestHarnessCodeReadyWorkspaces(t *testing.T) { +func TestWorkspaceController(t *testing.T) { gomega.RegisterFailHandler(ginkgo.Fail) fmt.Println("Creating ginkgo reporter for Test Harness: Junit and Debug Detail reporter") diff --git a/test/e2e/pkg/client/pod.go b/test/e2e/pkg/client/pod.go index ca91cabe6..a31d31442 100644 --- a/test/e2e/pkg/client/pod.go +++ b/test/e2e/pkg/client/pod.go @@ -33,8 +33,7 @@ func (w *K8sClient) PodDeployWaitUtil(label string) (deployed bool, err error) { return false, errors.New("timed out") case <-tick: desc := w.WaitForPodBySelectorRunning(config.Namespace, label, 180) - if desc != nil { - } else { + if desc == nil { return true, nil } } diff --git a/test/e2e/pkg/deploy/deserialize.go b/test/e2e/pkg/deploy/deserialize.go deleted file mode 100644 index ac7b62c70..000000000 --- a/test/e2e/pkg/deploy/deserialize.go +++ /dev/null @@ -1,56 +0,0 @@ -// -// 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" - "io/ioutil" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes/scheme" -) - -func deserializePluginRegistryDeployment() (pluginRegistry *appsv1.Deployment, err error) { - file, err := ioutil.ReadFile("deploy/registry/local/deployment.yaml") - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - return nil, err - } - deployment := string(file) - decode := scheme.Codecs.UniversalDeserializer().Decode - object, _, err := decode([]byte(deployment), nil, nil) - if err != nil { - fmt.Println("Failed to deserialize yaml %s", err) - return nil, err - } - pluginRegistry = object.(*appsv1.Deployment) - return pluginRegistry, nil -} - -func deserializePluginRegistryService() (pluginRegistry *corev1.Service, err error) { - file, err := ioutil.ReadFile("deploy/registry/local/service.yaml") - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - return nil, err - } - deployment := string(file) - decode := scheme.Codecs.UniversalDeserializer().Decode - object, _, err := decode([]byte(deployment), nil, nil) - if err != nil { - fmt.Println("Failed to deserialize yaml %s", err) - return nil, err - } - pluginRegistry = object.(*corev1.Service) - return pluginRegistry, nil -} diff --git a/test/e2e/pkg/deploy/plugin_registry.go b/test/e2e/pkg/deploy/plugin_registry.go deleted file mode 100644 index 9ca633a93..000000000 --- a/test/e2e/pkg/deploy/plugin_registry.go +++ /dev/null @@ -1,53 +0,0 @@ -// -// 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" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" -) - -func (w *Deployment) CreatePluginRegistryDeployment() (err error) { - label := "app=che-plugin-registry" - deployment, err := deserializePluginRegistryDeployment() - - if err != nil { - fmt.Println("Failed to deserialize deployment") - return err - } - - deployment, err = w.kubeClient.Kube().AppsV1().Deployments(config.Namespace).Create(deployment) - - if err != nil { - fmt.Println("Failed to create deployment %s: %s", deployment.Name, err) - return err - } - - deploy, err := w.kubeClient.PodDeployWaitUtil(label) - if !deploy { - fmt.Println("Che Workspaces Controller not deployed") - return err - } - return nil -} - -func (w *Deployment) CreatePluginRegistryService() (err error) { - deserializeService, _ := deserializePluginRegistryService() - - _, err = w.kubeClient.Kube().CoreV1().Services(config.Namespace).Create(deserializeService) - if err != nil { - fmt.Println("Failed to create service %s: %s", deserializeService.Name, err) - return err - } - return nil -} From df13281d4fc5e3a5e2ebbbe8de60b3337dfc2718 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 21:06:02 +0200 Subject: [PATCH 04/11] Delete unnecessary folders and code Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 4 +- test/e2e/pkg/deploy/controller.go | 2 +- test/e2e/pkg/workspaces/deserialize.go | 48 -------------- test/e2e/pkg/workspaces/util.go | 89 -------------------------- 4 files changed, 3 insertions(+), 140 deletions(-) delete mode 100644 test/e2e/pkg/workspaces/deserialize.go delete mode 100644 test/e2e/pkg/workspaces/util.go diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index f5d7b30a8..96af0180c 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -22,8 +22,8 @@ import ( corev1 "k8s.io/api/core/v1" 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" - workspaces "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" "github.com/onsi/ginkgo" "github.com/onsi/ginkgo/reporters" "github.com/onsi/gomega" @@ -41,7 +41,7 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { fmt.Println("Starting to setup objects before run ginkgo suite") config.Namespace = "che-workspace-controller" - workspaces, err := workspaces.NewK8sClient() + workspaces, err := client.NewK8sClient() if err != nil { fmt.Println("Failed to create workspace client") } diff --git a/test/e2e/pkg/deploy/controller.go b/test/e2e/pkg/deploy/controller.go index 3c334d3ed..76bf1927a 100644 --- a/test/e2e/pkg/deploy/controller.go +++ b/test/e2e/pkg/deploy/controller.go @@ -58,7 +58,7 @@ func (w *Deployment) CreatePluginRegistryRoute() (err error) { } func (w *Deployment) CustomResourceDefinitions() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/crds") + cmd := exec.Command("oc", "apply", "-f", "deploy/crds") output, err := cmd.CombinedOutput() if err != nil && !strings.Contains(string(output), "AlreadyExists") { fmt.Println(err) diff --git a/test/e2e/pkg/workspaces/deserialize.go b/test/e2e/pkg/workspaces/deserialize.go deleted file mode 100644 index 5c8cd5c78..000000000 --- a/test/e2e/pkg/workspaces/deserialize.go +++ /dev/null @@ -1,48 +0,0 @@ -package workspaces - -import ( - "fmt" - "io/ioutil" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes/scheme" -) - -func deserializePluginRegistryDeployment() (pluginRegistry *appsv1.Deployment, err error) { - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - } - file, err := ioutil.ReadFile("deploy/registry/local/deployment.yaml") - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - } - deployment := string(file) - decode := scheme.Codecs.UniversalDeserializer().Decode - object, _, err := decode([]byte(deployment), nil, nil) - if err != nil { - fmt.Println("Failed to deserialize yaml %s", err) - return nil, err - } - pluginRegistry = object.(*appsv1.Deployment) - return pluginRegistry, nil -} - -func deserializePluginRegistryService() (pluginRegistry *corev1.Service, err error) { - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - } - file, err := ioutil.ReadFile("deploy/registry/local/service.yaml") - if err != nil { - fmt.Println("Failed to locate operator deployment yaml, %s", err) - } - deployment := string(file) - decode := scheme.Codecs.UniversalDeserializer().Decode - object, _, err := decode([]byte(deployment), nil, nil) - if err != nil { - fmt.Println("Failed to deserialize yaml %s", err) - return nil, err - } - pluginRegistry = object.(*corev1.Service) - return pluginRegistry, nil -} diff --git a/test/e2e/pkg/workspaces/util.go b/test/e2e/pkg/workspaces/util.go deleted file mode 100644 index 99bb9a1f9..000000000 --- a/test/e2e/pkg/workspaces/util.go +++ /dev/null @@ -1,89 +0,0 @@ -package workspaces - -import ( - "errors" - "fmt" - "time" - - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/metadata" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" -) - -func (w *CodeReady) PodDeployWaitUtil(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: - desc := w.WaitForPodBySelectorRunning(metadata.Namespace.Name, label, 180) - if desc != nil { - } else { - return true, nil - } - } - } -} - -// return a condition function that indicates whether the given pod is -// currently running -func (w *CodeReady) 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 - } -} - -// Poll up to timeout seconds for pod to enter running state. -// Returns an error if the pod never enters the running state. -func (w *CodeReady) waitForPodRunning(namespace, podName string, timeout time.Duration) error { - return wait.PollImmediate(time.Second, timeout, w.isPodRunning(podName, namespace)) -} - -// Returns the list of currently scheduled or running pods in `namespace` with the given selector -func (w *CodeReady) 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 -} - -// 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 *CodeReady) WaitForPodBySelectorRunning(namespace, selector string, timeout int) 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, time.Duration(timeout)*time.Second); err != nil { - return err - } - } - - return nil -} From c8101ee820096d3b04cd87ff51eccd33031ddad1 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 21:07:24 +0200 Subject: [PATCH 05/11] Fix typo Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index 96af0180c..c1178544a 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -75,14 +75,14 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { }, func(data []byte) {}) var _ = ginkgo.SynchronizedAfterSuite(func() { - workspaces, err := workspaces.NewK8sClient() + workspaces, err := client.NewK8sClient() if err != nil { _ = fmt.Errorf("Failed to uninstall workspace controller %s", err) } if err = workspaces.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { - _ = fmt.Errorf("Failed to deploy workspace controller %s", err) + _ = fmt.Errorf("Failed to uninstall workspace controller %s", err) } }, func() {}) From 448950ef80abed4fb7417ee8c50b713e0398da09 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 21:41:44 +0200 Subject: [PATCH 06/11] Panic if tests cannot create namespace Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 8 ++++---- test/e2e/pkg/client/pod.go | 3 ++- test/e2e/pkg/deploy/controller.go | 3 ++- test/e2e/pkg/tests/cloud_shell_tests.go | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index c1178544a..12fcbde2b 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -14,11 +14,12 @@ package cmd import ( "fmt" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" - deploy2 "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" "path/filepath" "testing" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" + deploy2 "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -50,7 +51,7 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { ns, err = workspaces.Kube().CoreV1().Namespaces().Create(ns) if err != nil { - fmt.Println("Failed to create namespace") + panic(err) } deploy := deploy2.NewDeployment(workspaces) @@ -86,7 +87,6 @@ var _ = ginkgo.SynchronizedAfterSuite(func() { } }, func() {}) - func TestWorkspaceController(t *testing.T) { gomega.RegisterFailHandler(ginkgo.Fail) diff --git a/test/e2e/pkg/client/pod.go b/test/e2e/pkg/client/pod.go index a31d31442..799ff1529 100644 --- a/test/e2e/pkg/client/pod.go +++ b/test/e2e/pkg/client/pod.go @@ -15,9 +15,10 @@ package client import ( "errors" "fmt" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" "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" diff --git a/test/e2e/pkg/deploy/controller.go b/test/e2e/pkg/deploy/controller.go index 76bf1927a..f2611dfba 100644 --- a/test/e2e/pkg/deploy/controller.go +++ b/test/e2e/pkg/deploy/controller.go @@ -14,9 +14,10 @@ package deploy import ( "fmt" - "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" "os/exec" "strings" + + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" ) func (w *Deployment) DeployWorkspacesController() (err error) { diff --git a/test/e2e/pkg/tests/cloud_shell_tests.go b/test/e2e/pkg/tests/cloud_shell_tests.go index 29f73129a..60d3d4ffc 100644 --- a/test/e2e/pkg/tests/cloud_shell_tests.go +++ b/test/e2e/pkg/tests/cloud_shell_tests.go @@ -14,6 +14,7 @@ package tests import ( "fmt" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" "github.com/onsi/ginkgo" "github.com/onsi/gomega" @@ -24,7 +25,6 @@ var _ = ginkgo.Describe("[Create Cloud Shell Workspace]", func() { label := "che.workspace_name=cloud-shell" k8sClient, err := client.NewK8sClient() if err != nil { - //TODO make sure it's the right way to fail here ginkgo.Fail("Failed to create k8s client: " + err.Error()) return } @@ -36,4 +36,4 @@ var _ = ginkgo.Describe("[Create Cloud Shell Workspace]", func() { } gomega.Expect(err).NotTo(gomega.HaveOccurred()) }) -}) \ No newline at end of file +}) From 4f7b08a5b95abcc439aa8c644b45f58ea9020426 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 21:44:36 +0200 Subject: [PATCH 07/11] Delete more unnecessary code Signed-off-by: flacatus --- test/e2e/pkg/deploy/controller.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/e2e/pkg/deploy/controller.go b/test/e2e/pkg/deploy/controller.go index f2611dfba..979a50064 100644 --- a/test/e2e/pkg/deploy/controller.go +++ b/test/e2e/pkg/deploy/controller.go @@ -48,16 +48,6 @@ func (w *Deployment) CreateAllOperatorRoles() (err error) { return err } -func (w *Deployment) CreatePluginRegistryRoute() (err error) { - cmd := exec.Command("oc", "apply", "--namespace", config.Namespace, "-f", "deploy/registry/local/os") - output, err := cmd.CombinedOutput() - fmt.Println(string(output)) - if err != nil && !strings.Contains(string(output), "AlreadyExists") { - fmt.Println(err) - } - return err -} - func (w *Deployment) CustomResourceDefinitions() (err error) { cmd := exec.Command("oc", "apply", "-f", "deploy/crds") output, err := cmd.CombinedOutput() From e88c1937a5fe1a33489d52a06831e760e9a03607 Mon Sep 17 00:00:00 2001 From: flacatus Date: Wed, 3 Jun 2020 22:02:09 +0200 Subject: [PATCH 08/11] Delete unnecessary constant Signed-off-by: flacatus --- test/e2e/pkg/client/oc.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/pkg/client/oc.go b/test/e2e/pkg/client/oc.go index 73e3bd204..e46aa891a 100644 --- a/test/e2e/pkg/client/oc.go +++ b/test/e2e/pkg/client/oc.go @@ -14,13 +14,13 @@ 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) { - const namespace = "che-workspace-controller" - cmd := exec.Command("oc", "apply", "--namespace", namespace, "-f", filePath) + 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") { From 932b29d025dd6d127618e45a6edc7cd44f167130 Mon Sep 17 00:00:00 2001 From: flacatus Date: Thu, 4 Jun 2020 00:59:27 +0200 Subject: [PATCH 09/11] Fix variable gap Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index 12fcbde2b..65a1f7b8b 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -18,7 +18,7 @@ import ( "testing" "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" - deploy2 "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" + "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -54,21 +54,21 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { panic(err) } - deploy := deploy2.NewDeployment(workspaces) + controller := deploy.NewDeployment(workspaces) - if err := deploy.CreateAllOperatorRoles(); err != nil { + if err := controller.CreateAllOperatorRoles(); err != nil { _ = fmt.Errorf("Failed to create roles in clusters %s", err) } - if err := deploy.CreateOperatorClusterRole(); err != nil { + if err := controller.CreateOperatorClusterRole(); err != nil { _ = fmt.Errorf("Failed to create roles in clusters %s", err) } - if err := deploy.CustomResourceDefinitions(); err != nil { + if err := controller.CustomResourceDefinitions(); err != nil { _ = fmt.Errorf("Failed to add custom resources definitions to cluster %s", err) } - if err := deploy.DeployWorkspacesController(); err != nil { + if err := controller.DeployWorkspacesController(); err != nil { _ = fmt.Errorf("Failed to deploy workspace controller %s", err) } From 21e2de68eb406f2c67d1c95bbfb75b205fc6d13f Mon Sep 17 00:00:00 2001 From: flacatus Date: Thu, 4 Jun 2020 10:19:42 +0200 Subject: [PATCH 10/11] Minor improvements Signed-off-by: flacatus --- test/e2e/cmd/workspaces_test.go | 30 +++------- test/e2e/pkg/client/client.go | 1 + test/e2e/pkg/client/pod.go | 79 ++++++++++++------------- test/e2e/pkg/deploy/controller.go | 34 +++++++---- test/e2e/pkg/tests/cloud_shell_tests.go | 2 +- 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/test/e2e/cmd/workspaces_test.go b/test/e2e/cmd/workspaces_test.go index 65a1f7b8b..4c4ce3125 100644 --- a/test/e2e/cmd/workspaces_test.go +++ b/test/e2e/cmd/workspaces_test.go @@ -20,7 +20,6 @@ import ( "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/config" "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/deploy" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/che-incubator/che-workspace-operator/test/e2e/pkg/client" @@ -42,26 +41,26 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { fmt.Println("Starting to setup objects before run ginkgo suite") config.Namespace = "che-workspace-controller" - workspaces, err := client.NewK8sClient() + k8sClient, err := client.NewK8sClient() if err != nil { fmt.Println("Failed to create workspace client") + panic(err) } - ns := newNamespace() - ns, err = workspaces.Kube().CoreV1().Namespaces().Create(ns) + controller := deploy.NewDeployment(k8sClient) + err = controller.CreateNamespace() if err != nil { panic(err) } - controller := deploy.NewDeployment(workspaces) - + //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 roles in clusters %s", err) + _ = fmt.Errorf("Failed to create cluster roles in clusters %s", err) } if err := controller.CustomResourceDefinitions(); err != nil { @@ -76,13 +75,13 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { }, func(data []byte) {}) var _ = ginkgo.SynchronizedAfterSuite(func() { - workspaces, err := client.NewK8sClient() + k8sClient, err := client.NewK8sClient() if err != nil { _ = fmt.Errorf("Failed to uninstall workspace controller %s", err) } - if err = workspaces.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { + if err = k8sClient.Kube().CoreV1().Namespaces().Delete(config.Namespace, &metav1.DeleteOptions{}); err != nil { _ = fmt.Errorf("Failed to uninstall workspace controller %s", err) } }, func() {}) @@ -96,17 +95,4 @@ func TestWorkspaceController(t *testing.T) { fmt.Println("Running Workspace Controller e2e tests...") ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "Workspaces Controller Operator Tests", r) - -} - -func newNamespace() (ns *corev1.Namespace) { - return &corev1.Namespace{ - TypeMeta: metav1.TypeMeta{ - Kind: "Namespace", - APIVersion: corev1.SchemeGroupVersion.Version, - }, - ObjectMeta: metav1.ObjectMeta{ - Name: config.Namespace, - }, - } } diff --git a/test/e2e/pkg/client/client.go b/test/e2e/pkg/client/client.go index d373916d9..42dc52f83 100644 --- a/test/e2e/pkg/client/client.go +++ b/test/e2e/pkg/client/client.go @@ -10,6 +10,7 @@ // Red Hat, Inc. - initial API and implementation // + package client import ( diff --git a/test/e2e/pkg/client/pod.go b/test/e2e/pkg/client/pod.go index 799ff1529..d3a24fdca 100644 --- a/test/e2e/pkg/client/pod.go +++ b/test/e2e/pkg/client/pod.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" ) -func (w *K8sClient) PodDeployWaitUtil(label string) (deployed bool, err error) { +func (w *K8sClient) WaitForPodRunningByLabel(label string) (deployed bool, err error) { timeout := time.After(15 * time.Minute) tick := time.Tick(1 * time.Second) @@ -33,36 +33,35 @@ func (w *K8sClient) PodDeployWaitUtil(label string) (deployed bool, err error) { case <-timeout: return false, errors.New("timed out") case <-tick: - desc := w.WaitForPodBySelectorRunning(config.Namespace, label, 180) - if desc == nil { + err := w.WaitForRunningPodBySelector(config.Namespace, label, 3*time.Minute) + if err == nil { return true, nil } } } } -// 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() +// 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) - 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 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 false, 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 nil } // Returns the list of currently scheduled or running pods in `namespace` with the given selector @@ -76,26 +75,26 @@ func (w *K8sClient) ListPods(namespace, selector string) (*v1.PodList, error) { return podList, 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) WaitForPodBySelectorRunning(namespace, selector string, timeout int) 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) +// 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 fmt.Errorf("Pod not created yet in %s with label %s", namespace, selector) - } +// 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() - for _, pod := range podList.Items { - fmt.Println("Pod " + pod.Name + " created in namespace " + namespace + "...Checking startup data.") - if err := w.waitForPodRunning(namespace, pod.Name, time.Duration(timeout)*time.Second); err != nil { - return err + 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 } - - return nil -} +} \ No newline at end of file diff --git a/test/e2e/pkg/deploy/controller.go b/test/e2e/pkg/deploy/controller.go index 979a50064..a3dc40895 100644 --- a/test/e2e/pkg/deploy/controller.go +++ b/test/e2e/pkg/deploy/controller.go @@ -14,13 +14,24 @@ 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) DeployWorkspacesController() (err error) { +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() @@ -30,38 +41,41 @@ func (w *Deployment) DeployWorkspacesController() (err error) { return err } - deploy, err := w.kubeClient.PodDeployWaitUtil(label) - if !deploy { + deploy, err := w.kubeClient.WaitForPodRunningByLabel(label) + if !deploy || err != nil { fmt.Println("Che Workspaces Controller not deployed") return err } - return err + return nil } -func (w *Deployment) CreateAllOperatorRoles() (err error) { +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 err + return nil } -func (w *Deployment) CustomResourceDefinitions() (err error) { +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 err + return nil } -func (w *Deployment) CreateOperatorClusterRole() (err error) { +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 err + return nil } diff --git a/test/e2e/pkg/tests/cloud_shell_tests.go b/test/e2e/pkg/tests/cloud_shell_tests.go index 60d3d4ffc..0790fa139 100644 --- a/test/e2e/pkg/tests/cloud_shell_tests.go +++ b/test/e2e/pkg/tests/cloud_shell_tests.go @@ -29,7 +29,7 @@ var _ = ginkgo.Describe("[Create Cloud Shell Workspace]", func() { return } _ = k8sClient.OcApply("samples/cloud-shell.yaml") - deploy, err := k8sClient.PodDeployWaitUtil(label) + deploy, err := k8sClient.WaitForPodRunningByLabel(label) if !deploy { fmt.Println("Cloud Shell not deployed") From 5a56e1ba377230fff6eb23fb304906d750dfba92 Mon Sep 17 00:00:00 2001 From: flacatus Date: Fri, 5 Jun 2020 10:36:52 +0200 Subject: [PATCH 11/11] Add better description Signed-off-by: flacatus --- test/e2e/pkg/client/client.go | 3 +-- test/e2e/pkg/client/pod.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/e2e/pkg/client/client.go b/test/e2e/pkg/client/client.go index 42dc52f83..56e21df1f 100644 --- a/test/e2e/pkg/client/client.go +++ b/test/e2e/pkg/client/client.go @@ -10,7 +10,6 @@ // Red Hat, Inc. - initial API and implementation // - package client import ( @@ -22,7 +21,7 @@ type K8sClient struct { kubeClient *kubernetes.Clientset } -// NewCodeReady creates C, a workspaces used to expose common testing functions. +// 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 { diff --git a/test/e2e/pkg/client/pod.go b/test/e2e/pkg/client/pod.go index d3a24fdca..3dc0e8903 100644 --- a/test/e2e/pkg/client/pod.go +++ b/test/e2e/pkg/client/pod.go @@ -97,4 +97,4 @@ func (w *K8sClient) isPodRunning(podName, namespace string) wait.ConditionFunc { } return false, nil } -} \ No newline at end of file +}