Skip to content

Commit a607488

Browse files
authored
test(STONEO11Y-44): Add initial o11y tests to e2e (konflux-ci#398)
Setting up the framework for the o11y team e2e tests. Added Pending Labels to test to not to run this test as part of CI, till the deployment-related STONEO11Y-86 is completed. Signed-off-by: Sri Vignesh <sselvan@redhat.com>
1 parent 54334be commit a607488

File tree

6 files changed

+198
-0
lines changed

6 files changed

+198
-0
lines changed

cmd/e2e_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
_ "github.com/redhat-appstudio/e2e-tests/tests/has"
1919
_ "github.com/redhat-appstudio/e2e-tests/tests/integration-service"
2020
_ "github.com/redhat-appstudio/e2e-tests/tests/mvp-demo"
21+
_ "github.com/redhat-appstudio/e2e-tests/tests/o11y"
2122
_ "github.com/redhat-appstudio/e2e-tests/tests/release"
2223

2324
"flag"

pkg/framework/describe.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,7 @@ func IntegrationServiceSuiteDescribe(text string, args ...interface{}) bool {
4646
func MvpDemoSuiteDescribe(text string, args ...interface{}) bool {
4747
return Describe("[mvp-demo-suite "+text+"]", args, Ordered)
4848
}
49+
50+
func O11ySuiteDescribe(text string, args ...interface{}) bool {
51+
return Describe("[O11y-suite "+text+"]", args, Ordered)
52+
}

pkg/framework/framework.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/redhat-appstudio/e2e-tests/pkg/utils/has"
1414
"github.com/redhat-appstudio/e2e-tests/pkg/utils/integration"
1515
"github.com/redhat-appstudio/e2e-tests/pkg/utils/jvmbuildservice"
16+
"github.com/redhat-appstudio/e2e-tests/pkg/utils/o11y"
1617
"github.com/redhat-appstudio/e2e-tests/pkg/utils/release"
1718
"github.com/redhat-appstudio/e2e-tests/pkg/utils/spi"
1819
"github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton"
@@ -27,6 +28,7 @@ type ControllerHub struct {
2728
ReleaseController *release.SuiteController
2829
IntegrationController *integration.SuiteController
2930
JvmbuildserviceController *jvmbuildservice.SuiteController
31+
O11yController *o11y.SuiteController
3032
}
3133

3234
type Framework struct {
@@ -122,6 +124,11 @@ func InitControllerHub(cc *kubeCl.CustomClient) (*ControllerHub, error) {
122124
if err != nil {
123125
return nil, err
124126
}
127+
// Initialize o11y controller
128+
o11yController, err := o11y.NewSuiteController(cc)
129+
if err != nil {
130+
return nil, err
131+
}
125132

126133
return &ControllerHub{
127134
HasController: hasController,
@@ -132,6 +139,7 @@ func InitControllerHub(cc *kubeCl.CustomClient) (*ControllerHub, error) {
132139
ReleaseController: releaseController,
133140
IntegrationController: integrationController,
134141
JvmbuildserviceController: jvmbuildserviceController,
142+
O11yController: o11yController,
135143
}, nil
136144

137145
}

pkg/utils/common/controller.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
appsv1 "k8s.io/api/apps/v1"
3030
rbacv1 "k8s.io/api/rbac/v1"
3131
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
32+
"sigs.k8s.io/controller-runtime/pkg/client"
3233
rclient "sigs.k8s.io/controller-runtime/pkg/client"
3334
)
3435

@@ -634,3 +635,40 @@ func (s *SuiteController) CreateRoleBinding(roleBindingName, namespace, subjectK
634635
}
635636
return createdRoleBinding, nil
636637
}
638+
639+
// Delete all the PipelineRuns and Tasks associated to namespace
640+
func (s *SuiteController) DeleteAllPipelineRunsAndTasks(namespace string) error {
641+
// List all PipelineRuns in the namespace
642+
pipelineRunList := &v1beta1.PipelineRunList{}
643+
err := s.KubeRest().List(context.TODO(), pipelineRunList, &client.ListOptions{
644+
Namespace: namespace,
645+
})
646+
if err != nil {
647+
return err
648+
}
649+
650+
// Delete each PipelineRun and its associated tasks
651+
for _, pipelineRun := range pipelineRunList.Items {
652+
if err := s.KubeRest().Delete(context.TODO(), &pipelineRun, &client.DeleteOptions{}); err != nil {
653+
return err
654+
}
655+
for _, task := range pipelineRun.Spec.PipelineSpec.Tasks {
656+
taskObj := &v1beta1.Task{}
657+
if err := s.KubeRest().Get(context.TODO(), types.NamespacedName{
658+
Namespace: namespace,
659+
Name: task.TaskRef.Name,
660+
}, taskObj); err != nil {
661+
// Ignore "not found" errors since the task may have already been deleted
662+
if k8sErrors.IsNotFound(err) {
663+
continue
664+
}
665+
return err
666+
}
667+
if err := s.KubeRest().Delete(context.TODO(), taskObj, &client.DeleteOptions{}); err != nil {
668+
return err
669+
}
670+
}
671+
}
672+
673+
return nil
674+
}

pkg/utils/o11y/controller.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package o11y
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"math"
7+
"os/exec"
8+
"regexp"
9+
"strconv"
10+
11+
kubeCl "github.com/redhat-appstudio/e2e-tests/pkg/apis/kubernetes"
12+
)
13+
14+
type SuiteController struct {
15+
*kubeCl.CustomClient
16+
}
17+
18+
type MetricResult struct {
19+
Metric map[string]string `json:"metric"`
20+
Value []interface{} `json:"value"`
21+
}
22+
23+
func NewSuiteController(kube *kubeCl.CustomClient) (*SuiteController, error) {
24+
return &SuiteController{
25+
kube,
26+
}, nil
27+
}
28+
29+
func (h *SuiteController) convertBytesToMB(bytesValue float64) float64 {
30+
megabytesValue := bytesValue / (1000 * 1000)
31+
return math.Round(megabytesValue*10) / 10
32+
}
33+
34+
// Fetch metrics for given query
35+
func (h *SuiteController) GetMetrics(query string) ([]MetricResult, error) {
36+
37+
var result struct {
38+
Data struct {
39+
Result []MetricResult `json:"result"`
40+
} `json:"data"`
41+
}
42+
43+
// Temporary way to fetch the metrics, will be replaced by golang http client library
44+
// curl -X GET -kG "https://$THANOS_QUERIER_HOST/api/v1/query?" --data-urlencode "query="+query -H "Authorization: Bearer $TOKEN"
45+
curlCmd := exec.Command("curl", "-X", "GET", "-kG", "http://localhost:8080/api/v1/query", "--data-urlencode", "query="+query)
46+
output, err := curlCmd.Output()
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
err = json.Unmarshal(output, &result)
52+
if err != nil {
53+
return nil, err
54+
}
55+
56+
return result.Data.Result, nil
57+
}
58+
59+
func (h *SuiteController) GetRegexPodNameWithSize(podNameRegex string, results []MetricResult) (map[string]float64, error) {
60+
podNameWithSize := make(map[string]float64)
61+
regex, err := regexp.Compile(podNameRegex)
62+
if err != nil {
63+
return podNameWithSize, fmt.Errorf("error compiling regex pattern: %v", err)
64+
}
65+
66+
for _, res := range results {
67+
if podName, ok := res.Metric["pod"]; ok {
68+
if regex.MatchString(podName) {
69+
value := res.Value[1].(string)
70+
valueInBytes, err := strconv.ParseFloat(value, 64)
71+
if err != nil {
72+
return nil, fmt.Errorf("error parsing value for %s: %s", podName, err)
73+
}
74+
valueInMegabytes := h.convertBytesToMB(valueInBytes)
75+
podNameWithSize[podName] = valueInMegabytes
76+
}
77+
}
78+
}
79+
80+
if len(podNameWithSize) == 0 {
81+
return nil, fmt.Errorf("no pods matching the regex pattern were found")
82+
}
83+
84+
return podNameWithSize, nil
85+
}

tests/o11y/o11y.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package o11y
2+
3+
import (
4+
"fmt"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
9+
"github.com/redhat-appstudio/e2e-tests/pkg/framework"
10+
)
11+
12+
const (
13+
O11yUser = "o11y-e2e"
14+
)
15+
16+
var _ = framework.O11ySuiteDescribe("O11Y E2E tests", Label("o11y", "HACBS"), Pending, func() {
17+
18+
defer GinkgoRecover()
19+
var f *framework.Framework
20+
var err error
21+
22+
Describe("O11y test", Pending, func() {
23+
var testNamespace string
24+
25+
BeforeAll(func() {
26+
27+
f, err = framework.NewFramework(O11yUser)
28+
Expect(err).NotTo(HaveOccurred())
29+
testNamespace = f.UserNamespace
30+
31+
})
32+
AfterAll(func() {
33+
if !CurrentSpecReport().Failed() {
34+
// err := f.AsKubeAdmin.CommonController.DeleteAllPipelineRunsAndTasks(testNamespace)
35+
// Expect(err).NotTo(HaveOccurred())
36+
Expect(f.SandboxController.DeleteUserSignup(f.UserName)).NotTo(BeFalse())
37+
}
38+
})
39+
40+
It("E2E sample test for upload 50MB pod", Pending, func() {
41+
podNameRegex := ".*-upload-50mb-pod"
42+
query := fmt.Sprintf("last_over_time(container_network_transmit_bytes_total{namespace='%s', pod=~'%s'}[1h])", testNamespace, podNameRegex)
43+
44+
result, err := f.AsKubeAdmin.O11yController.GetMetrics(query)
45+
Expect(err).NotTo(HaveOccurred())
46+
47+
podNamesWithSize, err := f.AsKubeAdmin.O11yController.GetRegexPodNameWithSize(podNameRegex, result)
48+
Expect(err).NotTo(HaveOccurred())
49+
50+
for podName, podSize := range podNamesWithSize {
51+
GinkgoWriter.Printf("Pod: %s, Size: %.2f MB", podName, podSize)
52+
// Range limits are measured as part of STONEO11Y-15
53+
Expect(podSize).To(And(
54+
BeNumerically(">=", 53.00),
55+
BeNumerically("<=", 53.59),
56+
), fmt.Sprintf("%s: %.2f MB is not within the expected range.", podName, podSize))
57+
}
58+
59+
})
60+
})
61+
62+
})

0 commit comments

Comments
 (0)