Skip to content

Commit

Permalink
[KOGITO-1316] Travel Agency Openshift scenario (apache#221)
Browse files Browse the repository at this point in the history
Implemented scenario when Visa is not needed.
Other scenario will be delivered as another PR.

Signed-off-by: Karel Suta <[email protected]>
  • Loading branch information
sutaakar authored and MarianMacik committed Oct 3, 2023
1 parent 30728a1 commit a5c4bba
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 0 deletions.
44 changes: 44 additions & 0 deletions bddframework/features/deploy_travel_agency.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@quarkus
@cr
Feature: Deploy Travel agency service and verify its functionality

Background:
Given Namespace is created
And Kogito Operator is deployed with Infinispan and Kafka operators
And "CR" install Kogito Data Index with 1 replicas
And "CR" deploy service from example file "travelapp-kogito-travel-agency.yaml"
And Kogito application "kogito-travel-agency" has 1 pods running within 10 minutes
And HTTP GET request on service "kogito-travel-agency" with path "travels" is successful within 1 minutes

Scenario: Travel application without required Visa
When Start "travels" process on service "kogito-travel-agency" with body:
"""json
{
"traveller" : {
"firstName" : "John6",
"lastName" : "Doe",
"email" : "[email protected]",
"nationality" : "American",
"address" : {
"street" : "main street",
"city" : "Boston",
"zipCode" : "10005",
"country" : "US"
}
},
"trip" : {
"city" : "New York",
"country" : "US",
"begin" : "2019-12-10T00:00:00.000+02:00",
"end" : "2019-12-15T00:00:00.000+02:00"
}
}
"""
And Service "kogito-travel-agency" contains 1 instance of process with name "travels"
And Service "kogito-travel-agency" contains 1 task of process with name "travels" and task name "ConfirmTravel"
And Complete "ConfirmTravel" task on service "kogito-travel-agency" and process with name "travels" with body:
"""json
{}
"""

Then Service "kogito-travel-agency" contains 0 instances of process with name "travels"
29 changes: 29 additions & 0 deletions bddframework/framework/kogitoapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/yaml"

"github.com/gobuffalo/packr/v2"
"github.com/kiegroup/kogito-cloud-operator/pkg/apis/app/v1alpha1"
"github.com/kiegroup/kogito-cloud-operator/pkg/client/kubernetes"
)

const (
boxExamplesPath = "../../deploy/examples"
mavenArgsAppendEnvVar = "MAVEN_ARGS_APPEND"
mavenMirrorURLEnvVar = "MAVEN_MIRROR_URL"
)
Expand Down Expand Up @@ -137,6 +140,32 @@ func cliDeployExample(namespace string, kogitoAppDeployment KogitoAppDeployment)
return err
}

// DeployServiceFromExampleFile deploy service from example YAML file (example is located in deploy/examples folder)
func DeployServiceFromExampleFile(namespace, exampleFile string) error {
box := packr.New("examples", boxExamplesPath)
yamlContent, err := box.FindString(exampleFile)
if err != nil {
return fmt.Errorf("Error reading file %s: %v ", exampleFile, err)
}

// Create basic KogitoApp stub
kogitoApp := getKogitoAppStub(namespace, "name-should-be overwritten-from-yaml", nil)

// Apply content from yaml file
if err := yaml.NewYAMLOrJSONDecoder(strings.NewReader(yamlContent), len([]byte(yamlContent))).Decode(kogitoApp); err != nil {
return fmt.Errorf("Error while unmarshalling file: %v ", err)
}

// Apply custom image configuration
setupBuildImageStreams(kogitoApp)

// Create application
if _, err := kubernetes.ResourceC(kubeClient).CreateIfNotExists(kogitoApp); err != nil {
return fmt.Errorf("Error creating service %s: %v", kogitoApp.Name, err)
}
return nil
}

// SetKogitoAppReplicas sets the number of replicas for a Kogito application
func SetKogitoAppReplicas(namespace, name string, nbPods int) error {
GetLogger(namespace).Infof("Set Kogito application %s replica number to %d", name, nbPods)
Expand Down
27 changes: 27 additions & 0 deletions bddframework/framework/process.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2020 Red Hat, Inc. and/or its affiliates
//
// 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 framework

// StartProcess starts new process instance
func StartProcess(namespace, routeURI, processName, bodyFormat, bodyContent string) (err error) {
_, err = ExecuteHTTPRequest(namespace, "POST", routeURI, processName, bodyFormat, bodyContent)
return
}

// GetProcessInstances retrieves process instance of process name
func GetProcessInstances(namespace, routeURI, processName string) (foundProcessInstances []map[string]interface{}, err error) {
err = ExecuteHTTPRequestWithUnmarshalledResponse(namespace, "GET", routeURI, processName, "", "", &foundProcessInstances)
return
}
27 changes: 27 additions & 0 deletions bddframework/framework/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2020 Red Hat, Inc. and/or its affiliates
//
// 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 framework

// GetTasks retrieves tasks of specific process instance
func GetTasks(namespace, routeURI, processName, processInstanceID string) (foundTasks map[string]string, err error) {
err = ExecuteHTTPRequestWithUnmarshalledResponse(namespace, "GET", routeURI, processName+"/"+processInstanceID+"/tasks", "", "", &foundTasks)
return
}

// CompleteTask completes task
func CompleteTask(namespace, routeURI, processName, processInstanceID, taskName, taskID, bodyFormat, bodyContent string) (err error) {
_, err = ExecuteHTTPRequest(namespace, "POST", routeURI, processName+"/"+processInstanceID+"/"+taskName+"/"+taskID, bodyFormat, bodyContent)
return
}
2 changes: 2 additions & 0 deletions bddframework/steps/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (data *Data) RegisterAllSteps(s *godog.Suite) {
registerKubernetesSteps(s, data)
registerOperatorSteps(s, data)
registerPrometheusSteps(s, data)
registerProcessSteps(s, data)
registerTaskSteps(s, data)
}

// BeforeScenario configure the data before a scenario is launched
Expand Down
5 changes: 5 additions & 0 deletions bddframework/steps/kogitoapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func registerKogitoAppSteps(s *godog.Suite, data *Data) {
s.Step(`^"([^"]*)" deploy quarkus example service "([^"]*)" with native "([^"]*)" and persistence and events$`, data.deployQuarkusExampleServiceWithNativeAndPersistenceAndEvents)
s.Step(`^"([^"]*)" deploy spring boot example service "([^"]*)"$`, data.deploySpringBootExampleService)
s.Step(`^"([^"]*)" deploy spring boot example service "([^"]*)" with persistence$`, data.deploySpringBootExampleServiceWithPersistence)
s.Step(`^"CR" deploy service from example file "([^"]*)"$`, data.deployServiceFromExampleFile)

// Build steps
s.Step(`^Build "([^"]*)" is complete after (\d+) minutes$`, data.buildIsCompleteAfterMinutes)
Expand Down Expand Up @@ -133,6 +134,10 @@ func (data *Data) deploySpringBootExampleServiceWithPersistence(installerType, c
})
}

func (data *Data) deployServiceFromExampleFile(exampleFile string) error {
return framework.DeployServiceFromExampleFile(data.Namespace, exampleFile)
}

// Build steps
func (data *Data) buildIsCompleteAfterMinutes(buildName string, timeoutInMin int) error {
return framework.WaitForBuildComplete(data.Namespace, buildName, timeoutInMin)
Expand Down
58 changes: 58 additions & 0 deletions bddframework/steps/process.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2020 Red Hat, Inc. and/or its affiliates
//
// 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 steps

import (
"fmt"

"github.com/cucumber/godog"
"github.com/cucumber/godog/gherkin"
"github.com/kiegroup/kogito-cloud-operator/test/framework"
)

// registerProcessSteps register all process steps
func registerProcessSteps(s *godog.Suite, data *Data) {
s.Step(`^Start "([^"]*)" process on service "([^"]*)" with body:$`, data.startProcessOnService)
s.Step(`^Service "([^"]*)" contains (\d+) (?:instance|instances) of process with name "([^"]*)"$`, data.serviceContainsInstancesOfProcess)
}

func (data *Data) startProcessOnService(processName, serviceName string, body *gherkin.DocString) error {
routeURI, err := framework.WaitAndRetrieveRouteURI(data.Namespace, serviceName)
if err != nil {
return err
}

err = framework.StartProcess(data.Namespace, routeURI, processName, body.ContentType, body.Content)
if err != nil {
return err
}
return nil
}

func (data *Data) serviceContainsInstancesOfProcess(serviceName string, processInstances int, processName string) error {
routeURI, err := framework.WaitAndRetrieveRouteURI(data.Namespace, serviceName)
if err != nil {
return err
}

foundProcessInstances, err := framework.GetProcessInstances(data.Namespace, routeURI, processName)
if err != nil {
return err
}
if len(foundProcessInstances) != processInstances {
return fmt.Errorf("expected %d of process instances, but got %d", processInstances, len(foundProcessInstances))
}
return nil
}
111 changes: 111 additions & 0 deletions bddframework/steps/task.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2020 Red Hat, Inc. and/or its affiliates
//
// 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 steps

import (
"fmt"

"github.com/cucumber/godog"
"github.com/cucumber/godog/gherkin"
"github.com/kiegroup/kogito-cloud-operator/test/framework"
)

// registerTaskSteps register all task steps
func registerTaskSteps(s *godog.Suite, data *Data) {
s.Step(`^Service "([^"]*)" contains (\d+) (?:task|tasks) of process with name "([^"]*)" and task name "([^"]*)"$`, data.serviceContainsTasksOfProcessWithNameAndTaskName)
s.Step(`^Complete "([^"]*)" task on service "([^"]*)" and process with name "([^"]*)" with body:$`, data.completeTaskOnServiceAndProcessWithName)
}

func (data *Data) serviceContainsTasksOfProcessWithNameAndTaskName(serviceName string, numberOfTasks int, processName, taskName string) error {
routeURI, err := framework.WaitAndRetrieveRouteURI(data.Namespace, serviceName)
if err != nil {
return err
}

// We assume that one process instance is available, can be refactored if more flexibility needed
foundProcessInstances, err := framework.GetProcessInstances(data.Namespace, routeURI, processName)
if err != nil {
return err
}
if len(foundProcessInstances) == 0 {
return fmt.Errorf("no process instance found, expected one instance")
}
if len(foundProcessInstances) > 1 {
return fmt.Errorf("too many process instances found, expected one instance, but found %d instances", len(foundProcessInstances))
}

// We assume that only tasks with specified name exist, can be refactored if more flexibility needed
processInstanceID := foundProcessInstances[0]["id"].(string)
foundTasks, err := framework.GetTasks(data.Namespace, routeURI, processName, processInstanceID)
if err != nil {
return err
}
for _, foundTaskName := range foundTasks {
if taskName != foundTaskName {
return fmt.Errorf("found unexpected task name %s", foundTaskName)
}
}
if len(foundTasks) < numberOfTasks {
return fmt.Errorf("not enough tasks found, expected at least %d tasks, but found just %d tasks", numberOfTasks, len(foundTasks))
}

return nil
}

func (data *Data) completeTaskOnServiceAndProcessWithName(taskName, serviceName, processName string, body *gherkin.DocString) error {
routeURI, err := framework.WaitAndRetrieveRouteURI(data.Namespace, serviceName)
if err != nil {
return err
}

// We assume that one process instance is available, can be refactored if more flexibility needed
foundProcessInstances, err := framework.GetProcessInstances(data.Namespace, routeURI, processName)
if err != nil {
return err
}
if len(foundProcessInstances) == 0 {
return fmt.Errorf("no process instance found, expected one instance")
}
if len(foundProcessInstances) > 1 {
return fmt.Errorf("too many process instances found, expected one instance, but found %d instances", len(foundProcessInstances))
}

processInstanceID := foundProcessInstances[0]["id"].(string)
foundTasks, err := framework.GetTasks(data.Namespace, routeURI, processName, processInstanceID)
if err != nil {
return err
}

taskID, exists := getTaskID(foundTasks, taskName)
if !exists {
return fmt.Errorf("task with name %s not found", taskName)
}

err = framework.CompleteTask(data.Namespace, routeURI, processName, processInstanceID, taskName, taskID, body.ContentType, body.Content)
if err != nil {
return err
}
return nil
}

// getTaskID Returns task id of the task with name searchedTaskName and flag is the task with such name exists in tasks map
func getTaskID(tasks map[string]string, searchedTaskName string) (string, bool) {
for taskID, taskName := range tasks {
if taskName == searchedTaskName {
return taskID, true
}
}
return "", false
}

0 comments on commit a5c4bba

Please sign in to comment.