blob: 8e172455e763a02129775eb8ae89a5d44d66ce8e [file] [log] [blame]
// Copyright 2021 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 (
"errors"
"fmt"
"github.com/cucumber/godog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
hyperfoilv1alpha2 "github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/config"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/framework"
"github.com/apache/incubator-kie-kogito-serverless-operator/bddframework/pkg/installers"
)
const (
hyperfoilRunContextKey = "hyperfoil-run"
)
func registerHyperfoilSteps(ctx *godog.ScenarioContext, data *Data) {
ctx.Step(`^Hyperfoil Operator is deployed$`, data.hyperfoilOperatorIsDeployed)
ctx.Step(`^Hyperfoil instance "([^"]*)" is deployed within (\d+) (?:minute|minutes)$`, data.hyperfoilInstanceIsDeployedWithinMinutes)
ctx.Step(`^Hyperfoil Node scraper is deployed$`, data.hyperfoilNodeScraperIsDeployed)
ctx.Step(`^Create benchmark on Hyperfoil instance "([^"]*)" within (\d+) (?:minute|minutes) with content:$`, data.createBenchmarkOnHyperfoilInstanceWithinMinutesWithBody)
ctx.Step(`^Start benchmark "([^"]*)" on Hyperfoil instance "([^"]*)" within (\d+) (?:minute|minutes)$`, data.startBenchmarkOnHyperfoilInstanceWithinMinutes)
ctx.Step(`^Benchmark run on Hyperfoil instance "([^"]*)" finished within (\d+) (?:minute|minutes)$`, data.benchmarkRunOnHyperfoilInstanceFinishedWithinMinutes)
ctx.Step(`^Store benchmark statistics of Hyperfoil instance "([^"]*)" as "([^"]*)"$`, data.storeBenchmarkStatisticsOfHyperfoilInstance)
}
func (data *Data) hyperfoilOperatorIsDeployed() error {
return installers.GetHyperfoilInstaller().Install(data.Namespace)
}
func (data *Data) hyperfoilNodeScraperIsDeployed() error {
return installers.GetHyperfoilNodeScraperInstaller().Install(data.Namespace)
}
func (data *Data) hyperfoilInstanceIsDeployedWithinMinutes(name string, timeOutInMin int) error {
hyperfoil := getHyperfoilDefaultResource(name, data.Namespace)
framework.GetLogger(data.Namespace).Info("Creating Hyperfoil instance", "name", hyperfoil.Name)
if err := framework.CreateObject(hyperfoil); err != nil {
return err
}
return framework.WaitForPodsWithLabel(data.Namespace, "role", "controller", 1, 5)
}
func (data *Data) createBenchmarkOnHyperfoilInstanceWithinMinutesWithBody(hyperfoilName string, timeOutInMin int, body *godog.DocString) error {
return data.httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody(hyperfoilName, timeOutInMin, "benchmark", body)
}
func (data *Data) startBenchmarkOnHyperfoilInstanceWithinMinutes(benchmarkName, hyperfoilName string, timeOutInMin int) error {
uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName)
if err != nil {
return err
}
run := &HyperfoilRun{}
// Yes, GET request actually triggers benchmark run
requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("benchmark/%s/start", benchmarkName))
return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("HTTP %s request on path '%s' to be successful", requestInfo.HTTPMethod, requestInfo.Path), timeOutInMin,
func() (bool, error) {
err := framework.ExecuteHTTPRequestWithUnmarshalledResponse(data.Namespace, requestInfo, run)
if err != nil {
return false, err
}
if run != nil {
// Persist run ID into context, it is expected that one scenario run will operate on one Hyperfoil run
data.ScenarioContext[hyperfoilRunContextKey] = run.ID
return true, nil
}
return false, err
})
}
func (data *Data) benchmarkRunOnHyperfoilInstanceFinishedWithinMinutes(hyperfoilName string, timeOutInMin int) error {
runID := data.ScenarioContext[hyperfoilRunContextKey]
if len(runID) == 0 {
return errors.New("Hyperfoil run ID not found. Did you start the benchmark?")
}
uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName)
if err != nil {
return err
}
run := &HyperfoilRun{}
requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("run/%s", runID))
return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("HTTP %s request on path '%s' to be successful", requestInfo.HTTPMethod, requestInfo.Path), timeOutInMin,
func() (bool, error) {
err := framework.ExecuteHTTPRequestWithUnmarshalledResponse(data.Namespace, requestInfo, run)
if err != nil {
return false, err
}
if run != nil && run.Completed {
return true, nil
}
return false, err
})
}
func (data *Data) storeBenchmarkStatisticsOfHyperfoilInstance(hyperfoilName, benchmarkFileName string) error {
runID := data.ScenarioContext[hyperfoilRunContextKey]
if len(runID) == 0 {
return errors.New("Hyperfoil run ID not found. Did you start the benchmark?")
}
uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName)
if err != nil {
return err
}
requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("run/%s/stats/all/json", runID))
stats, err := framework.ExecuteHTTPRequestWithStringResponse(data.Namespace, requestInfo)
if err != nil {
return err
}
err = framework.CreateFile(config.GetHyperfoilOutputDirectory(), benchmarkFileName, stats)
return err
}
func getHyperfoilDefaultResource(name, namespace string) *hyperfoilv1alpha2.Hyperfoil {
hyperfoil := &hyperfoilv1alpha2.Hyperfoil{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: hyperfoilv1alpha2.HyperfoilSpec{
PreHooks: []string{},
PostHooks: []string{},
},
}
if exists, err := framework.IsConfigMapExist(types.NamespacedName{Namespace: namespace, Name: installers.NodeScraperStartConfigMapName}); err != nil {
framework.GetLogger(namespace).Error(err, "Cannot fetch ConfigMap", "name", name, "namespace", namespace)
} else if exists {
hyperfoil.Spec.PreHooks = append(hyperfoil.Spec.PreHooks, installers.NodeScraperStartConfigMapName)
}
if exists, err := framework.IsConfigMapExist(types.NamespacedName{Namespace: namespace, Name: installers.NodeScraperStopConfigMapName}); err != nil {
framework.GetLogger(namespace).Error(err, "Cannot fetch ConfigMap", "name", name, "namespace", namespace)
} else if exists {
hyperfoil.Spec.PostHooks = append(hyperfoil.Spec.PostHooks, installers.NodeScraperStopConfigMapName)
}
if imageVersion := config.GetHyperfoilControllerImageVersion(); len(imageVersion) > 0 {
hyperfoil.Spec.Version = imageVersion
}
return hyperfoil
}
// HyperfoilRun represents informations about the Hyperfoil run
type HyperfoilRun struct {
ID string `json:"id"`
Completed bool `json:"completed"`
}