diff --git a/pkg/apisix/stream_route.go b/pkg/apisix/stream_route.go index f6377c8d78..aa15a3bf90 100644 --- a/pkg/apisix/stream_route.go +++ b/pkg/apisix/stream_route.go @@ -149,6 +149,7 @@ func (r *streamRouteClient) Create(ctx context.Context, obj *v1.StreamRoute) (*v zap.Int32("server_port", obj.ServerPort), zap.String("cluster", "default"), zap.String("url", r.url), + zap.String("sni", obj.SNI), ) if err := r.cluster.HasSynced(ctx); err != nil { diff --git a/pkg/apisix/stream_route_test.go b/pkg/apisix/stream_route_test.go index dfa669d43e..824d4c1c20 100644 --- a/pkg/apisix/stream_route_test.go +++ b/pkg/apisix/stream_route_test.go @@ -164,17 +164,21 @@ func TestStreamRouteClient(t *testing.T) { ID: "1", ServerPort: 8001, UpstreamId: "1", + SNI: "a.test.com", }) assert.Nil(t, err) assert.Equal(t, obj.ID, "1") + assert.Equal(t, obj.SNI, "a.test.com") obj, err = cli.Create(context.Background(), &v1.StreamRoute{ ID: "2", ServerPort: 8002, UpstreamId: "1", + SNI: "*.test.com", }) assert.Nil(t, err) assert.Equal(t, obj.ID, "2") + assert.Equal(t, obj.SNI, "*.test.com") // List objs, err := cli.List(context.Background()) @@ -200,4 +204,6 @@ func TestStreamRouteClient(t *testing.T) { assert.Nil(t, err) assert.Len(t, objs, 1) assert.Equal(t, "2", objs[0].ID) + assert.Equal(t, "112", objs[0].UpstreamId) + assert.Equal(t, "", objs[0].SNI) } diff --git a/pkg/kube/apisix/apis/config/v2/types.go b/pkg/kube/apisix/apis/config/v2/types.go index 666d7b6a11..c0acd02174 100644 --- a/pkg/kube/apisix/apis/config/v2/types.go +++ b/pkg/kube/apisix/apis/config/v2/types.go @@ -217,7 +217,8 @@ type ApisixRouteStream struct { type ApisixRouteStreamMatch struct { // IngressPort represents the port listening on the Ingress proxy server. // It should be pre-defined as APISIX doesn't support dynamic listening. - IngressPort int32 `json:"ingressPort" yaml:"ingressPort"` + IngressPort int32 `json:"ingressPort" yaml:"ingressPort"` + Host string `json:"host,omitempty" yaml:"host,omitempty"` } // ApisixRouteStreamBackend represents a TCP backend (a Kubernetes Service). diff --git a/pkg/providers/apisix/translation/apisix_route.go b/pkg/providers/apisix/translation/apisix_route.go index 40531158b4..2b5803f99e 100644 --- a/pkg/providers/apisix/translation/apisix_route.go +++ b/pkg/providers/apisix/translation/apisix_route.go @@ -836,6 +836,7 @@ func (t *translator) translateStreamRouteV2(ctx *translation.TranslateContext, a name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) sr.ServerPort = part.Match.IngressPort + sr.SNI = part.Match.Host ups, err := t.translateService(ar.Namespace, backend.ServiceName, backend.Subset, backend.ResolveGranularity, svcClusterIP, svcPort) if err != nil { return err @@ -901,6 +902,7 @@ func (t *translator) translateStreamRouteNotStrictlyV2(ctx *translation.Translat name := apisixv1.ComposeStreamRouteName(ar.Namespace, ar.Name, part.Name) sr.ID = id.GenID(name) sr.ServerPort = part.Match.IngressPort + sr.SNI = part.Match.Host ups, err := t.translateUpstreamNotStrictly(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort.IntVal, backend.ResolveGranularity) if err != nil { return err diff --git a/pkg/providers/utils/manifest_test.go b/pkg/providers/utils/manifest_test.go index 0085af8efe..1f21a69909 100644 --- a/pkg/providers/utils/manifest_test.go +++ b/pkg/providers/utils/manifest_test.go @@ -83,6 +83,7 @@ func TestDiffStreamRoutes(t *testing.T) { { ID: "3", ServerPort: 8080, + SNI: "a.test.com", }, } added, updated, deleted := DiffStreamRoutes(nil, news) @@ -92,6 +93,7 @@ func TestDiffStreamRoutes(t *testing.T) { assert.Equal(t, "1", added[0].ID) assert.Equal(t, "3", added[1].ID) assert.Equal(t, int32(8080), added[1].ServerPort) + assert.Equal(t, "a.test.com", added[1].SNI) olds := []*apisixv1.StreamRoute{ { @@ -100,6 +102,7 @@ func TestDiffStreamRoutes(t *testing.T) { { ID: "3", ServerPort: 8081, + SNI: "a.test.com", }, } added, updated, deleted = DiffStreamRoutes(olds, nil) @@ -109,6 +112,7 @@ func TestDiffStreamRoutes(t *testing.T) { assert.Equal(t, "2", deleted[0].ID) assert.Equal(t, "3", deleted[1].ID) assert.Equal(t, int32(8081), deleted[1].ServerPort) + assert.Equal(t, "a.test.com", deleted[1].SNI) added, updated, deleted = DiffStreamRoutes(olds, news) assert.Len(t, added, 1) @@ -116,6 +120,7 @@ func TestDiffStreamRoutes(t *testing.T) { assert.Len(t, updated, 1) assert.Equal(t, "3", updated[0].ID) assert.Equal(t, int32(8080), updated[0].ServerPort) + assert.Equal(t, "a.test.com", updated[0].SNI) assert.Len(t, deleted, 1) assert.Equal(t, "2", deleted[0].ID) } diff --git a/samples/deploy/crd/v1/ApisixRoute.yaml b/samples/deploy/crd/v1/ApisixRoute.yaml index cf0f8e586a..43f34ee5a5 100644 --- a/samples/deploy/crd/v1/ApisixRoute.yaml +++ b/samples/deploy/crd/v1/ApisixRoute.yaml @@ -796,6 +796,8 @@ spec: match: type: object properties: + host: + type: string ingressPort: type: integer minimum: 1 diff --git a/test/e2e/suite-ingress/suite-ingress-resource/stream.go b/test/e2e/suite-ingress/suite-ingress-resource/stream.go index aa3d9bc33e..499feb2ac4 100644 --- a/test/e2e/suite-ingress/suite-ingress-resource/stream.go +++ b/test/e2e/suite-ingress/suite-ingress-resource/stream.go @@ -150,3 +150,68 @@ spec: suites(scaffold.NewDefaultV2Scaffold()) }) }) + +var _ = ginkgo.Describe("suite-ingress-resource: ApisixRoute stream Testing SNI with v2", func() { + s := scaffold.NewDefaultV2Scaffold() + + ginkgo.It("stream route with sni when set host", func() { + backendSvc, backendSvcPort := s.DefaultHTTPBackend() + apisixRoute := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-tcp-route +spec: + stream: + - name: rule1 + protocol: TCP + match: + ingressPort: 9100 + host: a.test.com + backend: + serviceName: %s + servicePort: %d +`, backendSvc, backendSvcPort[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(apisixRoute)) + + err := s.EnsureNumApisixStreamRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + sr, err := s.ListApisixStreamRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), sr, 1) + assert.Equal(ginkgo.GinkgoT(), sr[0].ServerPort, int32(9100)) + assert.Equal(ginkgo.GinkgoT(), sr[0].SNI, "a.test.com") + }) + + ginkgo.It("no sni in stream route when not set host", func() { + backendSvc, backendSvcPort := s.DefaultHTTPBackend() + apisixRoute := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin-tcp-route +spec: + stream: + - name: rule1 + protocol: TCP + match: + ingressPort: 9100 + backend: + serviceName: %s + servicePort: %d +`, backendSvc, backendSvcPort[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(apisixRoute)) + + err := s.EnsureNumApisixStreamRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + sr, err := s.ListApisixStreamRoutes() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), sr, 1) + assert.Equal(ginkgo.GinkgoT(), sr[0].ServerPort, int32(9100)) + assert.Equal(ginkgo.GinkgoT(), sr[0].SNI, "") + }) +})