Skip to content

Commit 13fea7f

Browse files
committed
Test updates
Signed-off-by: mereta <[email protected]>
1 parent b3bdcb2 commit 13fea7f

29 files changed

+737
-274
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,8 @@ simplify-dashboards:
580580
run-perf-test:
581581
go test -v ./test/e2e/retina_perf_test.go -timeout 2h -tags=perf -count=1 -args -image-tag=${TAG} -image-registry=${IMAGE_REGISTRY} -image-namespace=${IMAGE_NAMESPACE}
582582

583+
run-e2e-test:
584+
go test -v ./test/e2e/ -timeout 1h -tags=e2e -count=1 -args -image-tag=${TAG} -image-registry=${IMAGE_REGISTRY} -image-namespace=${IMAGE_NAMESPACE}
583585
.PHONY: update-hubble
584586
update-hubble:
585587
@echo "Checking for Hubble updates..."

test/e2e/common/common.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
)
1818

1919
const (
20-
RetinaPort int = 10093
2120
// netObsRGtag is used to tag resources created by this test suite
2221
NetObsRGtag = "-e2e-netobs-"
2322
KubeSystemNamespace = "kube-system"
@@ -51,6 +50,9 @@ var (
5150
RetinaAdvancedProfilePath = func(rootDir string) string {
5251
return filepath.Join(rootDir, "test", "profiles", "advanced", "values.yaml")
5352
}
53+
HubbleChartPath = func(rootDir string) string {
54+
return filepath.Join(rootDir, "deploy", "hubble", "manifests", "controller", "helm", "retina")
55+
}
5456
KubeConfigFilePath = func(rootDir string) string {
5557
return filepath.Join(rootDir, "test", "e2e", "test.pem")
5658
}

test/e2e/common/validate-metric.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//nolint:revive // package name "common" is used across the E2E test suite
12
package common
23

34
import (
@@ -8,22 +9,21 @@ import (
89
prom "github.com/microsoft/retina/test/e2e/framework/prometheus"
910
)
1011

11-
var (
12-
ErrMetricFound = errors.New("unexpected metric found")
13-
)
12+
var ErrMetricFound = errors.New("unexpected metric found")
1413

1514
type ValidateMetric struct {
1615
ForwardedPort string
1716
MetricName string
1817
ValidMetrics []map[string]string
1918
ExpectMetric bool
19+
PartialMatch bool // If true, only the specified labels need to match (metric can have additional labels)
2020
}
2121

2222
func (v *ValidateMetric) Run() error {
2323
promAddress := fmt.Sprintf("http://localhost:%s/metrics", v.ForwardedPort)
2424

2525
for _, validMetric := range v.ValidMetrics {
26-
err := prom.CheckMetric(promAddress, v.MetricName, validMetric)
26+
err := prom.CheckMetric(promAddress, v.MetricName, validMetric, v.PartialMatch)
2727
if err != nil {
2828
// If we expect the metric not to be found, return nil if it's not found.
2929
if !v.ExpectMetric && errors.Is(err, prom.ErrNoMetricFound) {

test/e2e/framework/constants/networking.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package constants
22

33
const (
4+
MetricsEndpoint = "metrics"
5+
46
TCP = "TCP"
57
UDP = "UDP"
68
IPV4 = "IPv4"
79
IPTableRuleDrop = "IPTABLE_RULE_DROP"
810
SYN = "SYN"
9-
SYN_ACK = "SYN-ACK"
11+
SYNACK = "SYN-ACK"
1012
ACK = "ACK"
1113
FIN = "FIN"
1214
RST = "RST"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package constants
2+
3+
const (
4+
// Metrics Port
5+
RetinaMetricsPort = "10093"
6+
7+
// MetricsName
8+
RetinaDropMetricName = "networkobservability_drop_count"
9+
RetinaForwardMetricName = "networkobservability_forward_count"
10+
11+
// Labels
12+
RetinaSourceLabel = "source"
13+
RetinaDestinationLabel = "destination"
14+
RetinaProtocolLabel = "protocol"
15+
RetinaReasonLabel = "reason"
16+
RetinaDirectionLabel = "direction"
17+
)

test/e2e/framework/kubernetes/create-agnhost-statefulset.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ var ErrLabelMissingFromPod = fmt.Errorf("label missing from pod")
1818

1919
const (
2020
AgnhostHTTPPort = 80
21-
AgnhostReplicas = 1
2221
AgnhostArchAmd64 = "amd64"
2322
AgnhostArchArm64 = "arm64"
2423
)
@@ -29,6 +28,7 @@ type CreateAgnhostStatefulSet struct {
2928
ScheduleOnSameNode bool
3029
KubeConfigFilePath string
3130
AgnhostArch string
31+
AgnhostReplicas *int
3232
}
3333

3434
func (c *CreateAgnhostStatefulSet) Run() error {
@@ -50,7 +50,13 @@ func (c *CreateAgnhostStatefulSet) Run() error {
5050
c.AgnhostArch = AgnhostArchAmd64
5151
}
5252

53-
agnhostStatefulSet := c.getAgnhostDeployment(c.AgnhostArch)
53+
// set default replicas to 1
54+
replicas := 1
55+
if c.AgnhostReplicas != nil {
56+
replicas = *c.AgnhostReplicas
57+
}
58+
59+
agnhostStatefulSet := c.getAgnhostDeployment(c.AgnhostArch, replicas)
5460

5561
err = CreateResource(ctx, agnhostStatefulSet, clientset)
5662
if err != nil {
@@ -79,8 +85,8 @@ func (c *CreateAgnhostStatefulSet) Stop() error {
7985
return nil
8086
}
8187

82-
func (c *CreateAgnhostStatefulSet) getAgnhostDeployment(arch string) *appsv1.StatefulSet {
83-
reps := int32(AgnhostReplicas)
88+
func (c *CreateAgnhostStatefulSet) getAgnhostDeployment(arch string, replicas int) *appsv1.StatefulSet {
89+
reps := int32(replicas)
8490

8591
var affinity *v1.Affinity
8692
if c.ScheduleOnSameNode {

test/e2e/framework/prometheus/prometheus.go

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ var (
2222
defaultRetryAttempts = 60
2323
)
2424

25-
func CheckMetric(promAddress, metricName string, validMetric map[string]string) error {
25+
func CheckMetric(promAddress, metricName string, validMetric map[string]string, partial ...bool) error {
2626
defaultRetrier := retry.Retrier{Attempts: defaultRetryAttempts, Delay: defaultRetryDelay}
2727

2828
ctx := context.Background()
2929
pctx, cancel := context.WithCancel(ctx)
3030
defer cancel()
3131

32+
// Default partial to false if not provided
33+
usePartial := len(partial) > 0 && partial[0]
34+
3235
metrics := map[string]*promclient.MetricFamily{}
3336
scrapeMetricsFn := func() error {
3437
log.Printf("checking for metrics on %s", promAddress)
@@ -42,7 +45,11 @@ func CheckMetric(promAddress, metricName string, validMetric map[string]string)
4245

4346
// loop through each metric to check for a match,
4447
// if none is found then log and return an error which will trigger a retry
45-
err = verifyValidMetricPresent(metricName, metrics, validMetric)
48+
if usePartial {
49+
err = verifyValidMetricPresentPartial(metricName, metrics, validMetric)
50+
} else {
51+
err = verifyValidMetricPresent(metricName, metrics, validMetric)
52+
}
4653
if err != nil {
4754
log.Printf("failed to find metric matching %s: %+v\n", metricName, validMetric)
4855
return ErrNoMetricFound
@@ -99,6 +106,43 @@ func verifyValidMetricPresent(metricName string, data map[string]*promclient.Met
99106
return fmt.Errorf("failed to find metric matching: %+v: %w", validMetric, ErrNoMetricFound)
100107
}
101108

109+
// verifyValidMetricPresentPartial checks if a metric exists with labels that contain
110+
// all the key-value pairs in validMetric (partial matching - the metric can have additional labels)
111+
func verifyValidMetricPresentPartial(metricName string, data map[string]*promclient.MetricFamily, validMetric map[string]string) error {
112+
for _, metric := range data {
113+
if metric.GetName() == metricName {
114+
for _, metric := range metric.GetMetric() {
115+
116+
// get all labels and values on the metric
117+
metricLabels := map[string]string{}
118+
for _, label := range metric.GetLabel() {
119+
metricLabels[label.GetName()] = label.GetValue()
120+
}
121+
122+
// if valid metric is empty, then we just need to make sure the metric and value is present
123+
if len(validMetric) == 0 && len(metricLabels) > 0 {
124+
return nil
125+
}
126+
127+
// Check if all key-value pairs in validMetric exist in metricLabels
128+
allMatch := true
129+
for key, value := range validMetric {
130+
if metricLabels[key] != value {
131+
allMatch = false
132+
break
133+
}
134+
}
135+
136+
if allMatch {
137+
return nil
138+
}
139+
}
140+
}
141+
}
142+
143+
return fmt.Errorf("failed to find metric matching: %+v: %w", validMetric, ErrNoMetricFound)
144+
}
145+
102146
func getAllPrometheusMetricsFromURL(url string) (map[string]*promclient.MetricFamily, error) {
103147
client := http.Client{}
104148
resp, err := client.Get(url) //nolint

test/e2e/jobs/jobs.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/microsoft/retina/test/e2e/scenarios/dns"
1414
"github.com/microsoft/retina/test/e2e/scenarios/drop"
1515
hubble_dns "github.com/microsoft/retina/test/e2e/scenarios/hubble/dns"
16+
hubble_drop "github.com/microsoft/retina/test/e2e/scenarios/hubble/drop"
1617
hubble_flow "github.com/microsoft/retina/test/e2e/scenarios/hubble/flow"
1718
hubble_service "github.com/microsoft/retina/test/e2e/scenarios/hubble/service"
1819
hubble_tcp "github.com/microsoft/retina/test/e2e/scenarios/hubble/tcp"
@@ -276,7 +277,7 @@ func UpgradeAndTestRetinaAdvancedMetrics(kubeConfigFilePath, chartPath, valuesFi
276277
return job
277278
}
278279

279-
func InstallAndTestHubbleMetrics(kubeConfigFilePath, chartPath string, testPodNamespace string) *types.Job {
280+
func InstallAndTestHubbleMetrics(kubeConfigFilePath, chartPath string) *types.Job {
280281
job := types.NewJob("Validate Hubble")
281282

282283
job.AddStep(&kubernetes.InstallHubbleHelmChart{
@@ -287,16 +288,23 @@ func InstallAndTestHubbleMetrics(kubeConfigFilePath, chartPath string, testPodNa
287288
TagEnv: generic.DefaultTagEnv,
288289
}, nil)
289290

290-
hubbleScrenarios := []*types.Scenario{
291-
hubble_dns.ValidateDNSMetric(),
292-
hubble_flow.ValidateFlowMetric(),
293-
//hubble_drop.ValidateDropMetric(),
294-
hubble_tcp.ValidateTCPMetric(),
291+
hubbleScenarios := []*types.Scenario{
295292
hubble_service.ValidateHubbleRelayService(),
296293
hubble_service.ValidateHubbleUIService(kubeConfigFilePath),
297294
}
298295

299-
for _, scenario := range hubbleScrenarios {
296+
for _, arch := range common.Architectures {
297+
hubbleScenarios = append(hubbleScenarios,
298+
hubble_dns.ValidateDNSMetric(arch),
299+
hubble_flow.ValidatePodToPodIntraNodeHubbleFlowMetric(arch),
300+
hubble_flow.ValidatePodToPodInterNodeHubbleFlowMetric(arch),
301+
hubble_flow.ValidatePodToWorldHubbleFlowMetric(arch),
302+
hubble_drop.ValidateDropMetric(arch),
303+
hubble_tcp.ValidateTCPMetric(arch),
304+
)
305+
}
306+
307+
for _, scenario := range hubbleScenarios {
300308
job.AddScenario(scenario)
301309
}
302310

test/e2e/retina_e2e_test.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ func TestE2ERetina(t *testing.T) {
2626
// Get to root of the repo by going up two directories
2727
rootDir := filepath.Dir(filepath.Dir(cwd))
2828

29-
hubblechartPath := filepath.Join(rootDir, "deploy", "hubble", "manifests", "controller", "helm", "retina")
30-
3129
err = jobs.LoadGenericFlags().Run()
3230
require.NoError(t, err, "failed to load generic flags")
3331

@@ -55,17 +53,9 @@ func TestE2ERetina(t *testing.T) {
5553
advanceMetricsE2E.Run(ctx)
5654

5755
// Install and test Hubble metrics
58-
hubbleMetricsE2E := types.NewRunner(t, jobs.InstallAndTestHubbleMetrics(kubeConfigFilePath, hubblechartPath, common.TestPodNamespace))
56+
hubbleMetricsE2E := types.NewRunner(t, jobs.InstallAndTestHubbleMetrics(common.KubeConfigFilePath(rootDir), common.HubbleChartPath(rootDir)))
5957
hubbleMetricsE2E.Run(ctx)
6058

61-
// Install Retina basic and test captures
62-
captureE2E := types.NewRunner(t,
63-
jobs.ValidateCapture(
64-
common.KubeConfigFilePath(rootDir),
65-
"default"),
66-
)
67-
validatehubble.Run(ctx)
68-
6959
// Install Retina basic and test captures
7060
captureE2E := types.NewRunner(t,
7161
jobs.ValidateCapture(

test/e2e/scenarios/dns/scenarios.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ package dns
55
import (
66
"fmt"
77
"math/rand"
8-
"strconv"
98
"time"
109

1110
"github.com/microsoft/retina/test/e2e/common"
11+
"github.com/microsoft/retina/test/e2e/framework/constants"
1212
"github.com/microsoft/retina/test/e2e/framework/kubernetes"
1313
"github.com/microsoft/retina/test/e2e/framework/types"
1414
)
@@ -95,8 +95,8 @@ func ValidateBasicDNSMetrics(scenarioName string, req *RequestValidationParams,
9595
Step: &kubernetes.PortForward{
9696
Namespace: common.KubeSystemNamespace,
9797
LabelSelector: "k8s-app=retina",
98-
LocalPort: strconv.Itoa(common.RetinaPort),
99-
RemotePort: strconv.Itoa(common.RetinaPort),
98+
LocalPort: constants.RetinaMetricsPort,
99+
RemotePort: constants.RetinaMetricsPort,
100100
Endpoint: "metrics",
101101
OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace
102102
},
@@ -209,8 +209,8 @@ func ValidateAdvancedDNSMetrics(scenarioName string, req *RequestValidationParam
209209
Step: &kubernetes.PortForward{
210210
Namespace: common.KubeSystemNamespace,
211211
LabelSelector: "k8s-app=retina",
212-
LocalPort: strconv.Itoa(common.RetinaPort),
213-
RemotePort: strconv.Itoa(common.RetinaPort),
212+
LocalPort: constants.RetinaMetricsPort,
213+
RemotePort: constants.RetinaMetricsPort,
214214
Endpoint: "metrics",
215215
OptionalLabelAffinity: "app=" + agnhostName, // port forward to a pod on a node that also has this pod with this label, assuming same namespace
216216
},

0 commit comments

Comments
 (0)