From f8f8b41fa28fa54ebb0fac94912cd46434b7eff7 Mon Sep 17 00:00:00 2001 From: Qianglin Li Date: Mon, 14 Aug 2023 11:26:39 +0800 Subject: [PATCH] feat: support eureka registry (#464) Signed-off-by: charlie --- Makefile.core.mk | 4 + go.mod | 8 + go.sum | 21 ++ registry/eureka/client/http_client.go | 204 ++++++++++++ registry/eureka/client/plan.go | 80 +++++ registry/eureka/client/struct.go | 23 ++ registry/eureka/watcher.go | 304 ++++++++++++++++++ registry/reconcile/reconcile.go | 9 + test/e2e/conformance/base/manifests.yaml | 105 ++++++ .../tests/httproute-eureka-registry.go | 60 ++++ .../tests/httproute-eureka-registry.yaml | 46 +++ test/e2e/e2e_test.go | 1 + 12 files changed, 865 insertions(+) create mode 100644 registry/eureka/client/http_client.go create mode 100644 registry/eureka/client/plan.go create mode 100644 registry/eureka/client/struct.go create mode 100644 registry/eureka/watcher.go create mode 100644 test/e2e/conformance/tests/httproute-eureka-registry.go create mode 100644 test/e2e/conformance/tests/httproute-eureka-registry.yaml diff --git a/Makefile.core.mk b/Makefile.core.mk index d56eebad..1bb2ece9 100644 --- a/Makefile.core.mk +++ b/Makefile.core.mk @@ -238,11 +238,15 @@ kube-load-image: $(tools/kind) ## Install the Higress image to a kind cluster us tools/hack/docker-pull-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/dubbo-provider-demo 0.0.1 tools/hack/docker-pull-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/nacos-standlone-rc3 1.0.0-RC3 tools/hack/docker-pull-image.sh docker.io/hashicorp/consul 1.16.0 + tools/hack/docker-pull-image.sh docker.io/charlie1380/eureka-registry-provider v0.3.0 + tools/hack/docker-pull-image.sh docker.io/bitinit/eureka latest tools/hack/docker-pull-image.sh registry.cn-hangzhou.aliyuncs.com/2456868764/httpbin 1.0.2 tools/hack/kind-load-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/dubbo-provider-demo 0.0.1 tools/hack/kind-load-image.sh registry.cn-hangzhou.aliyuncs.com/hinsteny/nacos-standlone-rc3 1.0.0-RC3 tools/hack/kind-load-image.sh docker.io/hashicorp/consul 1.16.0 tools/hack/kind-load-image.sh registry.cn-hangzhou.aliyuncs.com/2456868764/httpbin 1.0.2 + tools/hack/kind-load-image.sh docker.io/charlie1380/eureka-registry-provider v0.3.0 + tools/hack/kind-load-image.sh docker.io/bitinit/eureka latest # run-higress-e2e-test starts to run ingress e2e tests. .PHONY: run-higress-e2e-test run-higress-e2e-test: diff --git a/go.mod b/go.mod index 048f0fb7..fe8c4f31 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.5 require ( github.com/agiledragon/gomonkey/v2 v2.9.0 + github.com/avast/retry-go/v4 v4.3.4 github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 github.com/dubbogo/gost v1.13.1 github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 @@ -26,6 +27,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/hashicorp/consul/api v1.23.0 github.com/hashicorp/go-multierror v1.1.1 + github.com/hudl/fargo v1.4.0 github.com/nacos-group/nacos-sdk-go v1.0.8 github.com/nacos-group/nacos-sdk-go/v2 v2.1.2 github.com/pkg/errors v0.9.1 @@ -78,6 +80,7 @@ require ( github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect + github.com/clbanning/mxj v1.8.4 // indirect github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa // indirect github.com/containerd/continuity v0.1.0 // indirect github.com/coreos/go-oidc/v3 v3.1.0 // indirect @@ -93,6 +96,7 @@ require ( github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/color v1.14.1 // indirect + github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect @@ -144,6 +148,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/miekg/dns v1.1.43 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect @@ -155,6 +160,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect + github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v1.0.2 // indirect @@ -194,10 +200,12 @@ require ( google.golang.org/api v0.59.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a // indirect + gopkg.in/gcfg.v1 v1.2.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.22.2 // indirect k8s.io/component-base v0.22.2 // indirect diff --git a/go.sum b/go.sum index f5458200..5c7b85c3 100644 --- a/go.sum +++ b/go.sum @@ -188,6 +188,8 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/avast/retry-go/v4 v4.3.4 h1:pHLkL7jvCvP317I8Ge+Km2Yhntv3SdkJm7uekkqbKhM= +github.com/avast/retry-go/v4 v4.3.4/go.mod h1:rv+Nla6Vk3/ilU0H51VHddWHiwimzX66yZ0JT6T+UvE= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -252,6 +254,8 @@ github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -467,6 +471,9 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2 h1:cZqz+yOJ/R64LcKjNQOdARott/jP7BnUQ9Ah7KaZCvw= +github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8 h1:a9ENSRDFBUPkJ5lCgVZh26+ZbGyoVJG7yb5SSzF5H54= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -708,6 +715,7 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -792,6 +800,8 @@ github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/hudl/fargo v1.4.0 h1:ZDDILMbB37UlAVLlWcJ2Iz1XuahZZTDZfdCKeclfq2s= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= @@ -843,6 +853,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -1088,6 +1099,7 @@ github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1270,8 +1282,10 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5-0.20210205191134-5ec6847320e5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1312,7 +1326,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1320,7 +1336,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -2081,6 +2100,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= @@ -2099,6 +2119,7 @@ gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/registry/eureka/client/http_client.go b/registry/eureka/client/http_client.go new file mode 100644 index 00000000..5a7a44e8 --- /dev/null +++ b/registry/eureka/client/http_client.go @@ -0,0 +1,204 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// 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 client + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "github.com/avast/retry-go/v4" + "github.com/hudl/fargo" + "istio.io/pkg/log" +) + +var httpClient = http.DefaultClient + +type EurekaHttpClient interface { + GetApplications() (*Applications, error) + GetApplication(name string) (*fargo.Application, error) + ScheduleAppUpdates(name string, stop <-chan struct{}) <-chan fargo.AppUpdate + GetDelta() (*Applications, error) +} + +func NewEurekaHttpClient(config EurekaHttpConfig) EurekaHttpClient { + return &eurekaHttpClient{config} +} + +type EurekaHttpConfig struct { + BaseUrl string + ConnectTimeoutSeconds int // default 30 + PollInterval int //default 30 + Retries int // default 3 + RetryDelayTime int // default 100ms + EnableDelta bool +} + +func NewDefaultConfig() EurekaHttpConfig { + return EurekaHttpConfig{ + ConnectTimeoutSeconds: 10, + PollInterval: 30, + EnableDelta: true, + Retries: 3, + RetryDelayTime: 100, + } +} + +type eurekaHttpClient struct { + EurekaHttpConfig +} + +func (e *eurekaHttpClient) GetApplications() (*Applications, error) { + return e.getApplications("/apps") +} + +func (e *eurekaHttpClient) GetApplication(name string) (*fargo.Application, error) { + return e.getApplication("/apps/" + name) +} + +func (e *eurekaHttpClient) ScheduleAppUpdates(name string, stop <-chan struct{}) <-chan fargo.AppUpdate { + updates := make(chan fargo.AppUpdate) + + consume := func(app *fargo.Application, err error) { + // Drop attempted sends when the consumer hasn't received the last buffered update + select { + case updates <- fargo.AppUpdate{App: app, Err: err}: + default: + } + } + + go func() { + ticker := time.NewTicker(time.Duration(e.PollInterval) * time.Second) + defer ticker.Stop() + + for { + select { + case <-stop: + close(updates) + return + case <-ticker.C: + consume(e.GetApplication(name)) + } + } + }() + + return updates +} + +func (e *eurekaHttpClient) GetDelta() (*Applications, error) { + if !e.EnableDelta { + return nil, fmt.Errorf("failed to get DeltaAppliation, enableDelta is false") + } + return e.getApplications("/apps/delta") +} + +func (c *eurekaHttpClient) getApplications(path string) (*Applications, error) { + res, code, err := c.request(path) + if err != nil { + log.Errorf("Failed to get applications, err: %v", err) + return nil, err + } + + if code != 200 { + log.Warnf("Failed to get applications, http code : %v", code) + } + + var rj fargo.GetAppsResponseJson + if err = json.Unmarshal(res, &rj); err != nil { + log.Errorf("Failed to unmarshal response body to fargo.GetAppResponseJosn, error: %v", err) + return nil, err + } + + apps := map[string]*fargo.Application{} + for idx := range rj.Response.Applications { + app := rj.Response.Applications[idx] + apps[app.Name] = app + } + + for name, app := range apps { + log.Debugf("Parsing metadata for app %v", name) + if err := app.ParseAllMetadata(); err != nil { + return nil, err + } + } + + return &Applications{ + Apps: apps, + HashCode: rj.Response.AppsHashcode, + VersionDelta: rj.Response.VersionsDelta, + }, nil +} + +func (c *eurekaHttpClient) getApplication(path string) (*fargo.Application, error) { + res, code, err := c.request(path) + if err != nil { + log.Errorf("Failed to get application, err: %v", err) + return nil, err + } + + if code != 200 { + log.Warnf("Failed to get application, http code : %v", code) + } + + var rj fargo.GetAppResponseJson + if err = json.Unmarshal(res, &rj); err != nil { + log.Errorf("Failed to unmarshal response body to fargo.GetAppResponseJson, error: %v", err) + return nil, err + } + + return &rj.Application, nil +} + +func (c *eurekaHttpClient) request(urlPath string) ([]byte, int, error) { + req, err := http.NewRequest("GET", c.getUrl(urlPath), nil) + if err != nil { + log.Errorf("Failed to new a Request, error: %v", err.Error()) + return nil, -1, err + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + retryConfig := []retry.Option{ + retry.Attempts(uint(c.Retries)), + retry.Delay(time.Duration(c.RetryDelayTime)), + } + + resp := &http.Response{} + err = retry.Do(func() error { + resp, err = httpClient.Do(req) + return err + }, retryConfig...) + + if err != nil { + log.Errorf("Failed to get response from eureka-server, error : %v", err) + return nil, -1, err + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Errorf("Failed to read request body, error : %v", err) + return nil, -1, err + } + + log.Infof("Get eureka response from url=%v", req.URL) + return body, resp.StatusCode, nil +} + +func (c *eurekaHttpClient) getUrl(path string) string { + return "http://" + c.BaseUrl + "/eureka" + path +} diff --git a/registry/eureka/client/plan.go b/registry/eureka/client/plan.go new file mode 100644 index 00000000..937828cd --- /dev/null +++ b/registry/eureka/client/plan.go @@ -0,0 +1,80 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// 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 client + +import ( + "github.com/hudl/fargo" + "istio.io/pkg/log" +) + +type Handler func(application *fargo.Application) error + +/* + * Plan can be used to get the latest information of a service + * + * (service B) ┌──────┐ + * ┌────────────►│Plan B│ + * │ Timer └──────┘ + * │ + * ┌───────────────┐ │ + * │ eureka-server ├────┤ + * └───────────────┘ │ + * │ + * │ + * │(service A) ┌──────┐ + * └────────────►│Plan A│ + * Timer └──────┘ + */ + +type Plan struct { + client EurekaHttpClient + stop chan struct{} + handler Handler +} + +func NewPlan(client EurekaHttpClient, serviceName string, handler Handler) *Plan { + p := &Plan{ + client: client, + stop: make(chan struct{}), + handler: handler, + } + + ch := client.ScheduleAppUpdates(serviceName, p.stop) + go p.watch(ch) + return p +} + +func (p *Plan) Stop() { + defer close(p.stop) + p.stop <- struct{}{} +} + +func (p *Plan) watch(ch <-chan fargo.AppUpdate) { + for { + select { + case <-p.stop: + log.Info("stop eureka plan") + return + case updateItem := <-ch: + if updateItem.Err != nil { + log.Error("get eureka application failed, error : %v", updateItem.Err) + continue + } + if err := p.handler(updateItem.App); err != nil { + log.Error("handle eureka application failed, error : %v", err) + } + } + } +} diff --git a/registry/eureka/client/struct.go b/registry/eureka/client/struct.go new file mode 100644 index 00000000..8e7ea41e --- /dev/null +++ b/registry/eureka/client/struct.go @@ -0,0 +1,23 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// 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 client + +import "github.com/hudl/fargo" + +type Applications struct { + Apps map[string]*fargo.Application + HashCode string + VersionDelta int +} diff --git a/registry/eureka/watcher.go b/registry/eureka/watcher.go new file mode 100644 index 00000000..29f0ae37 --- /dev/null +++ b/registry/eureka/watcher.go @@ -0,0 +1,304 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// 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 eureka + +import ( + "fmt" + "net" + "strconv" + "sync" + "time" + + "github.com/hudl/fargo" + "istio.io/api/networking/v1alpha3" + versionedclient "istio.io/client-go/pkg/clientset/versioned" + "istio.io/pkg/log" + ctrl "sigs.k8s.io/controller-runtime" + + apiv1 "github.com/alibaba/higress/api/networking/v1" + "github.com/alibaba/higress/pkg/common" + provider "github.com/alibaba/higress/registry" + . "github.com/alibaba/higress/registry/eureka/client" + "github.com/alibaba/higress/registry/memory" +) + +const ( + DefaultFullRefreshIntervalLimit = time.Second * 30 + suffix = "eureka" +) + +type watcher struct { + provider.BaseWatcher + apiv1.RegistryConfig + + WatchingServices map[string]*Plan `json:"watching_services"` + RegistryType provider.ServiceRegistryType `json:"registry_type"` + Status provider.WatcherStatus `json:"status"` + cache memory.Cache + mutex *sync.Mutex + stop chan struct{} + istioClient *versionedclient.Clientset + isStop bool + updateCacheWhenEmpty bool + + eurekaClient EurekaHttpClient + fullRefreshIntervalLimit time.Duration + deltaRefreshIntervalLimit time.Duration +} + +type WatcherOption func(w *watcher) + +func NewWatcher(cache memory.Cache, opts ...WatcherOption) (provider.Watcher, error) { + w := &watcher{ + WatchingServices: make(map[string]*Plan), + RegistryType: provider.Eureka, + Status: provider.UnHealthy, + cache: cache, + mutex: &sync.Mutex{}, + stop: make(chan struct{}), + } + + config, err := ctrl.GetConfig() + if err != nil { + return nil, err + } + + ic, err := versionedclient.NewForConfig(config) + if err != nil { + log.Errorf("can not new istio client, err:%v", err) + return nil, err + } + w.istioClient = ic + + w.fullRefreshIntervalLimit = DefaultFullRefreshIntervalLimit + + for _, opt := range opts { + opt(w) + } + + cfg := NewDefaultConfig() + cfg.BaseUrl = net.JoinHostPort(w.Domain, strconv.FormatUint(uint64(w.Port), 10)) + w.eurekaClient = NewEurekaHttpClient(cfg) + + return w, nil +} + +func WithEurekaFullRefreshInterval(refreshInterval int64) WatcherOption { + return func(w *watcher) { + if refreshInterval < int64(DefaultFullRefreshIntervalLimit) { + refreshInterval = int64(DefaultFullRefreshIntervalLimit) + } + w.fullRefreshIntervalLimit = time.Duration(refreshInterval) + } +} + +func WithType(t string) WatcherOption { + return func(w *watcher) { + w.Type = t + } +} + +func WithName(name string) WatcherOption { + return func(w *watcher) { + w.Name = name + } +} + +func WithDomain(domain string) WatcherOption { + return func(w *watcher) { + w.Domain = domain + } +} + +func WithPort(port uint32) WatcherOption { + return func(w *watcher) { + w.Port = port + } +} + +func WithUpdateCacheWhenEmpty(enable bool) WatcherOption { + return func(w *watcher) { + w.updateCacheWhenEmpty = enable + } +} + +func (w *watcher) Run() { + ticker := time.NewTicker(w.fullRefreshIntervalLimit) + defer ticker.Stop() + + w.Status = provider.ProbeWatcherStatus(w.Domain, strconv.FormatUint(uint64(w.Port), 10)) + w.doFullRefresh() + w.Ready(true) + + for { + select { + case <-ticker.C: + w.doFullRefresh() + case <-w.stop: + log.Info("eureka watcher(%v) is stopping ...", w.Name) + return + } + } +} + +func (w *watcher) Stop() { + w.mutex.Lock() + defer w.mutex.Unlock() + + for serviceName := range w.WatchingServices { + if err := w.unsubscribe(serviceName); err != nil { + log.Errorf("Failed to unsubscribe service : %v", serviceName) + continue + } + w.cache.DeleteServiceEntryWrapper(makeHost(serviceName)) + } + w.UpdateService() +} + +func (w *watcher) IsHealthy() bool { + return w.Status == provider.Healthy +} + +func (w *watcher) GetRegistryType() string { + return w.RegistryType.String() +} + +// doFullRefresh todo(lql): it's better to support deltaRefresh +func (w *watcher) doFullRefresh() { + w.mutex.Lock() + defer w.mutex.Unlock() + + applications, err := w.eurekaClient.GetApplications() + if err != nil { + log.Errorf("Failed to full fetch eureka services, error : %v", err) + return + } + + fetchedServices := applications.Apps + for serviceName := range w.WatchingServices { + if _, ok := fetchedServices[serviceName]; !ok { + if err = w.unsubscribe(serviceName); err != nil { + log.Errorf("Failed to unsubscribe service %v, error : %v", serviceName, err) + continue + } + } + } + + for serviceName := range fetchedServices { + if _, ok := w.WatchingServices[serviceName]; !ok { + if err = w.subscribe(fetchedServices[serviceName]); err != nil { + log.Errorf("Failed to subscribe service %v, error : %v", serviceName, err) + continue + } + } + } +} + +func (w *watcher) subscribe(service *fargo.Application) error { + if service == nil { + return fmt.Errorf("service is nil") + } + callback := func(service *fargo.Application) error { + defer w.UpdateService() + + if len(service.Instances) != 0 { + se, err := generateServiceEntry(service) + if err != nil { + return err + } + w.cache.UpdateServiceEntryWrapper(makeHost(service.Name), &memory.ServiceEntryWrapper{ + ServiceName: service.Name, + ServiceEntry: se, + Suffix: suffix, + RegistryType: w.Type, + }) + return nil + } + + if w.updateCacheWhenEmpty { + w.cache.DeleteServiceEntryWrapper(makeHost(service.Name)) + } + + return nil + } + + if err := callback(service); err != nil { + log.Errorf("failed to subscribe service %v, error: %v", service.Name, err) + return err + } + w.WatchingServices[service.Name] = NewPlan(w.eurekaClient, service.Name, callback) + return nil +} + +func (w *watcher) unsubscribe(serviceName string) error { + w.WatchingServices[serviceName].Stop() + delete(w.WatchingServices, serviceName) + w.UpdateService() + + return nil +} + +func makeHost(serviceName string) string { + return serviceName + common.DotSeparator + suffix +} + +func convertMap(m map[string]interface{}) map[string]string { + result := make(map[string]string) + for k, v := range m { + if value, ok := v.(string); ok { + result[k] = value + } + } + + return result +} + +func generateServiceEntry(app *fargo.Application) (*v1alpha3.ServiceEntry, error) { + portList := make([]*v1alpha3.Port, 0) + endpoints := make([]*v1alpha3.WorkloadEntry, 0) + + for _, instance := range app.Instances { + protocol := common.HTTP + if val, _ := instance.Metadata.GetString("protocol"); val != "" { + if protocol = common.ParseProtocol(val); protocol == common.Unsupported { + return nil, fmt.Errorf("unsupported protocol %v", val) + } + } + port := &v1alpha3.Port{ + Name: protocol.String(), + Number: uint32(instance.Port), + Protocol: protocol.String(), + } + if len(portList) == 0 { + portList = append(portList, port) + } + endpoint := v1alpha3.WorkloadEntry{ + Address: instance.IPAddr, + Ports: map[string]uint32{port.Protocol: port.Number}, + Labels: convertMap(instance.Metadata.GetMap()), + } + endpoints = append(endpoints, &endpoint) + } + + se := &v1alpha3.ServiceEntry{ + Hosts: []string{makeHost(app.Name)}, + Ports: portList, + Location: v1alpha3.ServiceEntry_MESH_INTERNAL, + Resolution: v1alpha3.ServiceEntry_STATIC, + Endpoints: endpoints, + } + + return se, nil +} diff --git a/registry/reconcile/reconcile.go b/registry/reconcile/reconcile.go index 9edb0e79..8928f43d 100644 --- a/registry/reconcile/reconcile.go +++ b/registry/reconcile/reconcile.go @@ -30,6 +30,7 @@ import ( . "github.com/alibaba/higress/registry" "github.com/alibaba/higress/registry/consul" "github.com/alibaba/higress/registry/direct" + "github.com/alibaba/higress/registry/eureka" "github.com/alibaba/higress/registry/memory" "github.com/alibaba/higress/registry/nacos" nacosv2 "github.com/alibaba/higress/registry/nacos/v2" @@ -196,6 +197,14 @@ func (r *Reconciler) generateWatcherFromRegistryConfig(registry *apiv1.RegistryC direct.WithDomain(registry.Domain), direct.WithPort(registry.Port), ) + case string(Eureka): + watcher, err = eureka.NewWatcher( + r.Cache, + eureka.WithName(registry.Name), + eureka.WithDomain(registry.Domain), + eureka.WithType(registry.Type), + eureka.WithPort(registry.Port), + ) default: return nil, errors.New("unsupported registry type:" + registry.Type) } diff --git a/test/e2e/conformance/base/manifests.yaml b/test/e2e/conformance/base/manifests.yaml index 8bd3ffd1..fc9247f9 100644 --- a/test/e2e/conformance/base/manifests.yaml +++ b/test/e2e/conformance/base/manifests.yaml @@ -459,4 +459,109 @@ spec: scheme: HTTP initialDelaySeconds: 20 periodSeconds: 20 +--- +# Eureka service registry +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: eureka-cm + namespace: higress-conformance-app-backend +data: + # if you want to deploy n instances of eureka cluster, + # you should set eureka_service_address: http://eureka-0.eureka:8761/eureka,...,http://eureka-(n-1).eureka:8761/eureka + eureka_service_address: "http://eureka-0.eureka.higress-conformance-app-backend.svc:8761/eureka" +--- +apiVersion: v1 +kind: Service +metadata: + name: eureka + namespace: higress-conformance-app-backend + labels: + app: eureka +spec: + clusterIP: None + ports: + - port: 8761 + name: eureka + selector: + app: eureka +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: eureka + namespace: higress-conformance-app-backend +spec: + serviceName: eureka + # n instances + replicas: 1 + selector: + matchLabels: + app: eureka + template: + metadata: + labels: + app: eureka + spec: + containers: + - name: eureka + image: bitinit/eureka + ports: + - containerPort: 8761 + name: http + protocol: TCP + resources: + requests: + memory: "500Mi" + cpu: "500m" + env: + - name: EUREKA_SERVER_ADDRESS + valueFrom: + configMapKeyRef: + name: eureka-cm + key: eureka_service_address + - name: ENVIRONMENT + value: "prod" + - name: JVM_OPTS + value: "-Xms1g -Xmx1g" + livenessProbe: + httpGet: + path: / + port: 8761 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: 8761 + initialDelaySeconds: 30 + periodSeconds: 10 +--- +apiVersion: v1 +kind: Pod +metadata: + name: eureka-registry-provider + namespace: higress-conformance-app-backend +spec: + containers: + - name: eureka-registry-provider + image: charlie1380/eureka-registry-provider:v0.3.0 + env: + - name: EUREKA_SERVER_ADDRESS + valueFrom: + configMapKeyRef: + name: eureka-cm + key: eureka_service_address + ports: + - containerPort: 8888 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: 8888 + scheme: HTTP + periodSeconds: 1 diff --git a/test/e2e/conformance/tests/httproute-eureka-registry.go b/test/e2e/conformance/tests/httproute-eureka-registry.go new file mode 100644 index 00000000..ef15d88c --- /dev/null +++ b/test/e2e/conformance/tests/httproute-eureka-registry.go @@ -0,0 +1,60 @@ +// Copyright (c) 2022 Alibaba Group Holding Ltd. +// +// 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 tests + +import ( + "testing" + "time" + + "github.com/alibaba/higress/test/e2e/conformance/utils/http" + "github.com/alibaba/higress/test/e2e/conformance/utils/suite" +) + +func init() { + HigressConformanceTests = append(HigressConformanceTests, HTTPRouteEurekaRegistry) +} + +var HTTPRouteEurekaRegistry = suite.ConformanceTest{ + ShortName: "HTTPRouteEurekaRegistry", + Description: "The Ingress in the higress-conformance-infra namespace uses the eureka service registry.", + Manifests: []string{"tests/httproute-eureka-registry.yaml"}, + Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { + testcases := []http.Assertion{ + { + Request: http.AssertionRequest{ + ActualRequest: http.Request{ + Host: "foo.com", + Path: "/healthz", + Method: "GET", + }, + }, + Response: http.AssertionResponse{ + ExpectedResponseNoRequest: true, + ExpectedResponse: http.Response{ + StatusCode: 200, + }, + }, + }, + } + timeoutConfig := suite.TimeoutConfig + // it may take more time + timeoutConfig.MaxTimeToConsistency = 120 * time.Second + t.Run("HTTPRoute Eureka Registry", func(t *testing.T) { + for _, testcase := range testcases { + http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, timeoutConfig, suite.GatewayAddress, testcase) + } + }) + }, +} diff --git a/test/e2e/conformance/tests/httproute-eureka-registry.yaml b/test/e2e/conformance/tests/httproute-eureka-registry.yaml new file mode 100644 index 00000000..312c7e1b --- /dev/null +++ b/test/e2e/conformance/tests/httproute-eureka-registry.yaml @@ -0,0 +1,46 @@ +# Copyright (c) 2022 Alibaba Group Holding Ltd. +# +# 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. + +apiVersion: networking.higress.io/v1 +kind: McpBridge +metadata: + name: default + namespace: higress-system +spec: + registries: + - domain: eureka.higress-conformance-app-backend.svc.cluster.local + name: eureka + port: 8761 + type: eureka +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + higress.io/destination: EUREKA-REGISTRY-PROVIDER.eureka + name: httproute-eureka-ingress + namespace: higress-system +spec: + ingressClassName: higress + rules: + - host: "foo.com" + http: + paths: + - pathType: Prefix + path: / + backend: + resource: + apiGroup: networking.higress.io + kind: McpBridge + name: default diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index d92372f0..97560477 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -97,6 +97,7 @@ func TestHigressConformanceTests(t *testing.T) { tests.HTTPRouteFullPathRegex, tests.HTTPRouteHttp2Rpc, tests.HTTPRouteConsulHttpBin, + tests.HTTPRouteEurekaRegistry, } }