From cc63aeec41cfd5e9a0f5a1233e02c7aad8cca3cd Mon Sep 17 00:00:00 2001 From: Adrian Moisey Date: Thu, 21 Nov 2024 07:11:52 +0200 Subject: [PATCH] Add e2e test --- test/e2e/framework/framework.go | 31 +++++++++++++++++++ test/e2e/framework/metrics.go | 17 ++++++++++ test/e2e/metrics/metrics.go | 55 +++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index 204da7df0..a28405155 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -732,6 +732,37 @@ func NewSingleIngressWithMultiplePaths(name string, paths []string, host, ns, se return newSingleIngress(name, ns, annotations, spec) } +func NewSingleIngressWithMultiplePathsOfDifferentTypes(name string, host, ns string, services map[string]networking.PathType, port int, annotations map[string]string) *networking.Ingress { + spec := networking.IngressSpec{ + IngressClassName: GetIngressClassName(ns), + Rules: []networking.IngressRule{ + { + Host: host, + IngressRuleValue: networking.IngressRuleValue{ + HTTP: &networking.HTTPIngressRuleValue{}, + }, + }, + }, + } + + for service, pathType := range services { + spec.Rules[0].IngressRuleValue.HTTP.Paths = append(spec.Rules[0].IngressRuleValue.HTTP.Paths, networking.HTTPIngressPath{ + Path: "/", + PathType: &pathType, + Backend: networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: service, + Port: networking.ServiceBackendPort{ + Number: int32(port), + }, + }, + }, + }) + } + + return newSingleIngress(name, ns, annotations, spec) +} + func newSingleIngressWithRules(name, path, host, ns, service string, port int, annotations map[string]string, tlsHosts []string) *networking.Ingress { pathtype := networking.PathTypePrefix spec := networking.IngressSpec{ diff --git a/test/e2e/framework/metrics.go b/test/e2e/framework/metrics.go index 774f1bd7e..dfc3a8754 100644 --- a/test/e2e/framework/metrics.go +++ b/test/e2e/framework/metrics.go @@ -56,3 +56,20 @@ func (f *Framework) GetMetric(metricName, ip string) (*dto.MetricFamily, error) return nil, fmt.Errorf("there is no metric with name %v", metricName) } + +func (f *Framework) GetLabelValue(metric *dto.Metric, labelName string) (string, bool) { + // Use the proto descriptor of the metric + // metricProto := &dto.Metric{} + // if err := metric.Write(metricProto); err != nil { + // fmt.Println("Error writing metric:", err) + // return "", false + // } + + // Iterate through the label pairs + for _, label := range metric.Label { + if label.GetName() == labelName { + return label.GetValue(), true + } + } + return "", false +} diff --git a/test/e2e/metrics/metrics.go b/test/e2e/metrics/metrics.go index bec09bb37..12b3f4ac3 100644 --- a/test/e2e/metrics/metrics.go +++ b/test/e2e/metrics/metrics.go @@ -26,6 +26,7 @@ import ( "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" + networking "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/ingress-nginx/test/e2e/framework" @@ -139,3 +140,57 @@ var _ = framework.IngressNginxDescribe("[metrics] exported prometheus metrics", assert.Nil(ginkgo.GinkgoT(), reqMetrics) }) }) + +var _ = framework.IngressNginxDescribe("[metrics] exported prometheus metrics when multiple services share a path", func() { + f := framework.NewDefaultFramework("metrics") + host := "foo.com" + + configuredServices := map[string]networking.PathType{ + framework.EchoService: networking.PathTypePrefix, + framework.HTTPBunService: networking.PathTypeExact, + } + + ginkgo.BeforeEach(func() { + f.NewEchoDeployment() + f.NewHttpbunDeployment() + f.EnsureIngress(framework.NewSingleIngressWithMultiplePathsOfDifferentTypes("multiplepaths", host, f.Namespace, configuredServices, 80, nil)) + f.WaitForNginxServer(host, + func(server string) bool { + return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) && + strings.Contains(server, "proxy_pass http://upstream_balancer;") + }) + }) + + ginkgo.It("ensures that each service has metrics reporting", func() { + f.HTTPTestClient(). + GET("/"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK) + f.HTTPTestClient(). + GET("/path"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK) + + time.Sleep(waitForMetrics) + + fetchedServices := []string{} + + ip := f.GetNginxPodIP() + mf, err := f.GetMetric("nginx_ingress_controller_requests", ip) + assert.Len(ginkgo.GinkgoT(), mf.Metric, 2) + + for _, metric := range mf.Metric { + label, _ := f.GetLabelValue(metric, "service") + fetchedServices = append(fetchedServices, label) + } + + assert.Equal(ginkgo.GinkgoT(), len(configuredServices), len(fetchedServices)) + + for _, service := range fetchedServices { + assert.Contains(ginkgo.GinkgoT(), configuredServices, service) + } + assert.NoError(ginkgo.GinkgoT(), err) + }) +})