Revisit CI to spin up clusters on-demand (#7159)

* Label ServiceBinding tests, so we can run them separately

They require installing additional components in the cluster (OLM, SBO, ...).

* Add GH Workflow for most of our tests (including cluster-related tests)

This allows to easily test even multiple versions of Kubernetes if needed.

For easier reporting and visualisation (and also avoid rebuilding odo many times),
Podman tests have also been relocated in this same Workflow.

Notes:
I tried to spin up lightweight OpenShift clusters but gave up because of several issues:
- MicroShift: I tried to use the aio container image, but this one is no longer maintained and is pretty old version of OCP.
Trying to follow the official guidelines did not work either because a base RHEL OS is mandatory
- CRC/OpenShiftLocal with Microshift preset: didnt pass the pre-checks because it detected an issue with nested virtualization on the GH Runner.

* Drop unused code in helper_oc and use namespace instead of project

When testing on Microshift, it seems that the Project API is purposely not implemented on MicroShift
This commit is contained in:
Armel Soro
2023-12-09 00:28:10 +01:00
committed by GitHub
parent 86a9a2ff20
commit b5ea6f144b
13 changed files with 382 additions and 111 deletions

View File

@@ -405,7 +405,7 @@ var _ = Describe("E2E Test", func() {
})
})
Context("starting with non-empty Directory add Binding", func() {
Context("starting with non-empty Directory add Binding", Label(helper.LabelServiceBinding), func() {
sendDataEntry := func(url string) map[string]interface{} {
values := map[string]interface{}{"name": "joe",
"location": "tokyo",

View File

@@ -35,17 +35,6 @@ func (oc OcRunner) Run(args ...string) *gexec.Session {
return session
}
// GetCurrentProject get currently active project in oc
// returns empty string if there no active project, or no access to the project
func (oc OcRunner) GetCurrentProject() string {
session := CmdRunner(oc.path, "project", "-q")
session.Wait()
if session.ExitCode() == 0 {
return strings.TrimSpace(string(session.Out.Contents()))
}
return ""
}
// GetCurrentServerURL retrieves the URL of the server we're currently connected to
// returns empty if not connected or an error occurred
func (oc OcRunner) GetCurrentServerURL() string {
@@ -60,36 +49,6 @@ func (oc OcRunner) GetCurrentServerURL() string {
return ""
}
// GetFirstURL returns the url of the first Route that it can find for given component
func (oc OcRunner) GetFirstURL(component string, app string, project string) string {
session := CmdRunner(oc.path, "get", "route",
"-n", project,
"-l", "app.kubernetes.io/instance="+component,
"-l", "app.kubernetes.io/part-of="+app,
"-o", "jsonpath={.items[0].spec.host}")
session.Wait()
if session.ExitCode() == 0 {
return string(session.Out.Contents())
}
return ""
}
// GetComponentRoutes run command to get the Routes in yaml format for given component
func (oc OcRunner) GetComponentRoutes(component string, app string, project string) string {
session := CmdRunner(oc.path, "get", "route",
"-n", project,
"-l", "app.kubernetes.io/instance="+component,
"-l", "app.kubernetes.io/part-of="+app,
"-o", "yaml")
session.Wait()
if session.ExitCode() == 0 {
return string(session.Out.Contents())
}
return ""
}
// ExecListDir returns dir list in specified location of pod
func (oc OcRunner) ExecListDir(podName string, projectName string, dir string) string {
stdOut := Cmd(oc.path, "exec", podName, "--namespace", projectName,
@@ -341,12 +300,13 @@ func (oc OcRunner) createAndSetRandNamespaceProject(projectName string) string {
fmt.Fprintf(GinkgoWriter, "Project %q already exists\n", projectName)
} else {
fmt.Fprintf(GinkgoWriter, "Creating a new project: %s\n", projectName)
session := Cmd(oc.path, "new-project", projectName).ShouldPass().Out()
session := Cmd(oc.path, "create", "namespace", projectName).ShouldPass().Out()
Expect(session).To(ContainSubstring(projectName))
}
// ListNamespaceProject makes sure that project eventually appears in the list of all namespaces/projects.
oc.ListNamespaceProject(projectName)
oc.addConfigMapForCleanup(projectName)
oc.SetProject(projectName)
return projectName
}
@@ -359,7 +319,7 @@ func (oc OcRunner) SetProject(namespace string) string {
// DeleteNamespaceProject deletes a specified project in oc cluster
func (oc OcRunner) DeleteNamespaceProject(projectName string, wait bool) {
fmt.Fprintf(GinkgoWriter, "Deleting project: %s\n", projectName)
Cmd(oc.path, "delete", "project", projectName, "--wait="+strconv.FormatBool(wait)).ShouldPass()
Cmd(oc.path, "delete", "namespace", projectName, "--wait="+strconv.FormatBool(wait)).ShouldPass()
}
func (oc OcRunner) GetAllPVCNames(namespace string) []string {
@@ -590,18 +550,18 @@ func (oc OcRunner) EnsureOperatorIsInstalled(partialOperatorName string) {
}
func (oc OcRunner) GetNamespaceProject() string {
return Cmd(oc.path, "get", "project").ShouldPass().Out()
return Cmd(oc.path, "get", "namespace").ShouldPass().Out()
}
func (oc OcRunner) HasNamespaceProject(name string) bool {
out := Cmd(oc.path, "get", "project", name, "-o", "jsonpath={.metadata.name}").
out := Cmd(oc.path, "get", "namespace", name, "-o", "jsonpath={.metadata.name}").
ShouldRun().Out()
return strings.Contains(out, name)
}
func (oc OcRunner) ListNamespaceProject(name string) {
Eventually(func() string {
return Cmd(oc.path, "get", "project").ShouldRun().Out()
return Cmd(oc.path, "get", "namespace").ShouldRun().Out()
}, 30, 1).Should(ContainSubstring(name))
}
@@ -610,7 +570,7 @@ func (oc OcRunner) GetActiveNamespace() string {
}
func (oc OcRunner) GetAllNamespaceProjects() []string {
output := Cmd(oc.path, "get", "projects",
output := Cmd(oc.path, "get", "namespaces",
"-o", "custom-columns=NAME:.metadata.name",
"--no-headers").ShouldPass().Out()
result, err := ExtractLines(output)

View File

@@ -5,9 +5,10 @@ import (
)
const (
LabelNoCluster = "nocluster"
LabelUnauth = "unauth"
LabelPodman = "podman"
LabelNoCluster = "nocluster"
LabelUnauth = "unauth"
LabelPodman = "podman"
LabelServiceBinding = "servicebinding"
)
func NeedsCluster(labels []string) bool {

View File

@@ -11,7 +11,7 @@ import (
"github.com/redhat-developer/odo/tests/helper"
)
var _ = Describe("odo add binding command tests", func() {
var _ = Describe("odo add binding command tests", Label(helper.LabelServiceBinding), func() {
// TODO: Add integration tests for the following cases when SBO is not installed
// * servicebinding with envvars does not send `odo dev` in an infinite loop
// * `odo dev` deletes service binding secrets for SB that is not present locally

View File

@@ -12,7 +12,7 @@ import (
"github.com/redhat-developer/odo/tests/helper"
)
var _ = Describe("odo describe/list binding command tests", func() {
var _ = Describe("odo describe/list binding command tests", Label(helper.LabelServiceBinding), func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)

View File

@@ -1811,7 +1811,7 @@ ComponentSettings:
})
})
When("Starting a PostgreSQL service", func() {
When("Starting a PostgreSQL service", Label(helper.LabelServiceBinding), func() {
BeforeEach(func() {
skipLogin := os.Getenv("SKIP_SERVICE_BINDING_TESTS")
if skipLogin == "true" {

View File

@@ -382,7 +382,7 @@ ComponentSettings:
})
}
When("deploying a ServiceBinding k8s resource", func() {
When("deploying a ServiceBinding k8s resource", Label(helper.LabelServiceBinding), func() {
const serviceBindingName = "my-nodejs-app-cluster-sample" // hard-coded from devfile-deploy-with-SB.yaml
BeforeEach(func() {
skipLogin := os.Getenv("SKIP_SERVICE_BINDING_TESTS")

View File

@@ -5,11 +5,12 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/redhat-developer/odo/tests/helper"
"github.com/tidwall/gjson"
"github.com/redhat-developer/odo/tests/helper"
)
var _ = Describe("odo list services tests", func() {
var _ = Describe("odo list services tests", Label(helper.LabelServiceBinding), func() {
var commonVar helper.CommonVar
var randomProject string

View File

@@ -11,7 +11,7 @@ import (
"github.com/redhat-developer/odo/tests/helper"
)
var _ = Describe("odo remove binding command tests", func() {
var _ = Describe("odo remove binding command tests", Label(helper.LabelServiceBinding), func() {
var commonVar helper.CommonVar
var _ = BeforeEach(func() {

View File

@@ -13,7 +13,7 @@ import (
. "github.com/onsi/gomega"
)
var _ = Describe("odo add binding interactive command tests", func() {
var _ = Describe("odo add binding interactive command tests", Label(helper.LabelServiceBinding), func() {
var commonVar helper.CommonVar
var serviceName string