forked from apache/incubator-kie-kogito-serverless-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[KOGITO-9940] Add E2E test cases for platform configured with Job Ser…
…vice and Data Index in a combination of scenarios with ephemeral and postgreSQL persistence in dev and production profiles (apache#337)
- Loading branch information
1 parent
e6779c6
commit 8216d94
Showing
20 changed files
with
1,084 additions
and
199 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
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,143 @@ | ||
// Copyright 2024 Apache Software Foundation (ASF) | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package e2e | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/url" | ||
"os" | ||
"os/exec" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/apache/incubator-kie-kogito-serverless-operator/test" | ||
"github.com/apache/incubator-kie-kogito-serverless-operator/test/utils" | ||
|
||
//nolint:golint | ||
//nolint:revive | ||
. "github.com/onsi/ginkgo/v2" | ||
|
||
//nolint:golint | ||
//nolint:revive | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
type health struct { | ||
Status string `json:"status"` | ||
} | ||
|
||
var ( | ||
upStatus string = "UP" | ||
) | ||
|
||
func verifyHealthStatusInPod(name string, namespace string) { | ||
// iterate over all containers to find the one that responds to the HTTP health endpoint | ||
Expect(name).NotTo(BeEmpty(), "pod name is empty") | ||
cmd := exec.Command("kubectl", "get", "pod", name, "-n", namespace, "-o", `jsonpath={.spec.containers[*].name}`) | ||
output, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
var errs error | ||
for _, cname := range strings.Split(string(output), " ") { | ||
var h *health | ||
h, err = getHealthStatusInContainer(name, cname, namespace) | ||
if err == nil { | ||
Expect(h.Status).To(Equal(upStatus)) | ||
return | ||
} | ||
if len(errs.Error()) > 0 { | ||
errs = fmt.Errorf("%v; %w", err, errs) | ||
} else { | ||
errs = err | ||
} | ||
} | ||
Expect(errs).NotTo(HaveOccurred(), fmt.Sprintf("No container was found that could respond to the health endpoint %v", errs)) | ||
|
||
} | ||
|
||
func getHealthStatusInContainer(podName string, containerName string, ns string) (*health, error) { | ||
h := health{} | ||
cmd := exec.Command("kubectl", "exec", "-t", podName, "-n", ns, "-c", containerName, "--", "curl", "-s", "localhost:8080/q/health") | ||
output, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
err = json.Unmarshal(output, &h) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to execute curl command against health endpoint in container %s:%v with output %s", containerName, err, output) | ||
} | ||
return &h, nil | ||
} | ||
func verifyWorkflowIsInRunningStateInNamespace(workflowName string, ns string) bool { | ||
cmd := exec.Command("kubectl", "get", "workflow", workflowName, "-n", ns, "-o", "jsonpath={.status.conditions[?(@.type=='Running')].status}") | ||
response, err := utils.Run(cmd) | ||
if err != nil { | ||
GinkgoWriter.Println(fmt.Errorf("failed to check if greeting workflow is running: %v", err)) | ||
return false | ||
} | ||
GinkgoWriter.Println(fmt.Sprintf("Got response %s", response)) | ||
|
||
if len(strings.TrimSpace(string(response))) == 0 { | ||
GinkgoWriter.Println(fmt.Errorf("empty response %v", err)) | ||
return false | ||
} | ||
status, err := strconv.ParseBool(string(response)) | ||
if err != nil { | ||
GinkgoWriter.Println(fmt.Errorf("failed to parse result %v", err)) | ||
return false | ||
} | ||
return status | ||
} | ||
|
||
func verifyWorkflowIsInRunningState(workflowName string, targetNamespace string) bool { | ||
return verifyWorkflowIsInRunningStateInNamespace(workflowName, targetNamespace) | ||
} | ||
|
||
func verifyWorkflowIsAddressable(workflowName string, targetNamespace string) bool { | ||
cmd := exec.Command("kubectl", "get", "workflow", workflowName, "-n", targetNamespace, "-o", "jsonpath={.status.address.url}") | ||
if response, err := utils.Run(cmd); err != nil { | ||
GinkgoWriter.Println(fmt.Errorf("failed to check if greeting workflow is running: %v", err)) | ||
return false | ||
} else { | ||
GinkgoWriter.Println(fmt.Sprintf("Got response %s", response)) | ||
if len(strings.TrimSpace(string(response))) > 0 { | ||
_, err := url.ParseRequestURI(string(response)) | ||
if err != nil { | ||
GinkgoWriter.Println(fmt.Errorf("failed to parse result %v", err)) | ||
return false | ||
} | ||
// The response is a valid URL so the test is passed | ||
return true | ||
} | ||
return false | ||
} | ||
} | ||
|
||
const ( | ||
minikubePlatform = "minikube" | ||
openshiftPlatform = "openshift" | ||
) | ||
|
||
func getSonataFlowPlatformFilename() string { | ||
if getClusterPlatform() == openshiftPlatform { | ||
return test.GetPlatformOpenshiftE2eTest() | ||
} | ||
return test.GetPlatformMinikubeE2eTest() | ||
} | ||
|
||
func getClusterPlatform() string { | ||
if v, ok := os.LookupEnv("CLUSTER_PLATFORM"); ok { | ||
return v | ||
} | ||
return minikubePlatform | ||
} |
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,123 @@ | ||
// Copyright 2024 Apache Software Foundation (ASF) | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package e2e | ||
|
||
import ( | ||
//nolint:golint | ||
//nolint:revive | ||
"bytes" | ||
"fmt" | ||
"math/rand" | ||
"os/exec" | ||
"path/filepath" | ||
"strings" | ||
"time" | ||
|
||
"github.com/apache/incubator-kie-kogito-serverless-operator/test" | ||
"github.com/apache/incubator-kie-kogito-serverless-operator/test/utils" | ||
. "github.com/onsi/ginkgo/v2" | ||
|
||
//nolint:golint | ||
//nolint:revive | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
const ( | ||
ephemeral = "ephemeral" | ||
postgreSQL = "postgreSQL" | ||
dev = "dev" | ||
production = "prod" | ||
) | ||
|
||
var _ = Describe("Validate the persistence", Ordered, func() { | ||
|
||
var ( | ||
projectDir string | ||
targetNamespace string | ||
) | ||
|
||
BeforeEach(func() { | ||
targetNamespace = fmt.Sprintf("test-%d", rand.Intn(1024)+1) | ||
cmd := exec.Command("kubectl", "create", "namespace", targetNamespace) | ||
_, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
}) | ||
AfterEach(func() { | ||
// Remove resources in test namespace with no failure | ||
if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { | ||
cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait") | ||
_, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
} | ||
}) | ||
var _ = Context("with platform services", func() { | ||
|
||
DescribeTable("when creating a simple workflow", func(testcaseDir string, profile string, persistenceType string) { | ||
By("Deploy the SonataFlowPlatform CR") | ||
var manifests []byte | ||
EventuallyWithOffset(1, func() error { | ||
var err error | ||
cmd := exec.Command("kubectl", "kustomize", filepath.Join(projectDir, | ||
testcaseDir, profile, persistenceType)) | ||
manifests, err = utils.Run(cmd) | ||
return err | ||
}, time.Minute, time.Second).Should(Succeed()) | ||
cmd := exec.Command("kubectl", "create", "-n", targetNamespace, "-f", "-") | ||
cmd.Stdin = bytes.NewBuffer(manifests) | ||
_, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
By("Wait for SonatatFlowPlatform CR to complete deployment") | ||
// wait for service deployments to be ready | ||
EventuallyWithOffset(1, func() error { | ||
cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app=sonataflow-platform", "--for", "condition=Ready", "--timeout=5s") | ||
_, err = utils.Run(cmd) | ||
return err | ||
}, 10*time.Minute, 5).Should(Succeed()) | ||
By("Evaluate status of service's health endpoint") | ||
cmd = exec.Command("kubectl", "get", "pod", "-l", "app=sonataflow-platform", "-n", targetNamespace, "-ojsonpath={.items[*].metadata.name}") | ||
output, err := utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
// remove the last CR that is added by default as the last character of the string. | ||
for _, pn := range strings.Split(string(output), " ") { | ||
verifyHealthStatusInPod(pn, targetNamespace) | ||
} | ||
By("Deploy the SonataFlow CR") | ||
cmd = exec.Command("kubectl", "create", "-n", targetNamespace, "-f", filepath.Join(projectDir, | ||
testcaseDir, profile, persistenceType, "sonataflow")) | ||
manifests, err = utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
By("Retrieve SonataFlow CR name") | ||
cmd = exec.Command("kubectl", "get", "sonataflow", "-n", targetNamespace, `-ojsonpath={.items[*].metadata.name}`) | ||
output, err = utils.Run(cmd) | ||
Expect(err).NotTo(HaveOccurred()) | ||
sfNames := strings.TrimRight(string(output), " ") | ||
|
||
By("Evaluate status of SonataFlow CR") | ||
for _, sf := range strings.Split(string(sfNames), " ") { | ||
Expect(sf).NotTo(BeEmpty(), "sonataflow name is empty") | ||
EventuallyWithOffset(1, func() bool { | ||
return verifyWorkflowIsInRunningStateInNamespace(sf, targetNamespace) | ||
}, 5*time.Minute, 5).Should(BeTrue()) | ||
} | ||
}, | ||
Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a dev profile", test.GetSonataFlowE2EPlatformServicesDirectory(), dev, ephemeral), | ||
Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a production profile", test.GetSonataFlowE2EPlatformServicesDirectory(), production, ephemeral), | ||
Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a dev profile", test.GetSonataFlowE2EPlatformServicesDirectory(), dev, postgreSQL), | ||
Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a production profile", test.GetSonataFlowE2EPlatformServicesDirectory(), production, postgreSQL), | ||
) | ||
|
||
}) | ||
}) |
Oops, something went wrong.