diff --git a/.github/workflows/_docker_build.yaml b/.github/workflows/_docker_build.yaml index dac643036f..756c8c9958 100644 --- a/.github/workflows/_docker_build.yaml +++ b/.github/workflows/_docker_build.yaml @@ -98,7 +98,7 @@ jobs: - name: Docker meta id: meta - uses: docker/metadata-action@v5.0.0 + uses: docker/metadata-action@v5.1.0 with: images: kong/kubernetes-ingress-controller flavor: | diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index f7893d3999..d83552d190 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -40,7 +40,7 @@ jobs: password: ${{ secrets.DOCKER_TOKEN }} - name: Docker meta id: meta - uses: docker/metadata-action@v5.0.0 + uses: docker/metadata-action@v5.1.0 with: images: kong/nightly-ingress-controller tags: ${{ steps.tags-standard.outputs.TAGS_STANDARD }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6f168c55a4..f6a2a02dc8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -97,7 +97,7 @@ jobs: password: ${{ secrets.DOCKER_TOKEN }} - name: Docker meta id: meta - uses: docker/metadata-action@v5.0.0 + uses: docker/metadata-action@v5.1.0 with: images: kong/kubernetes-ingress-controller flavor: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec3c3b921..b366a28ef7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -99,6 +99,8 @@ Adding a new version? You'll need three changes: [#5220](https://github.com/Kong/kubernetes-ingress-controller/pull/5220) - Added support for GRPC over HTTP (without TLS) in Gateway API. [#5128](https://github.com/Kong/kubernetes-ingress-controller/pull/5128) +- Added `-init-cache-sync-duration` CLI flag. This flag configures how long the controller waits for Kubernetes resources to populate at startup before generating the initial Kong configuration. It also fixes a bug that removed the default 5 second wait period. + [#5238](https://github.com/Kong/kubernetes-ingress-controller/pull/5238) - Added support in Gateway Discovery for specifying that the Admin API should use HTTP via the appProtocol field on the admin port. - [#5251](https://github.com/Kong/kubernetes-ingress-controller/pull/5251) diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index 12de5cfad3..f16e5c6b45 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -39,6 +39,7 @@ | `--gateway-discovery-dns-strategy` | `dns-strategy` | DNS strategy to use when creating Gateway's Admin API addresses. One of: ip, service, pod. | `"ip"` | | `--health-probe-bind-address` | `string` | The address the probe endpoint binds to. | `:10254` | | `--ingress-class` | `string` | Name of the ingress class to route through this controller. | `kong` | +| `--init-cache-sync-duration` | `duration` | The initial delay to wait for Kubernetes object caches to be synced before the initial configuration. | `5s` | | `--kong-admin-ca-cert` | `string` | PEM-encoded CA certificate to verify Kong's Admin TLS certificate. Mutually exclusive with --kong-admin-ca-cert-file. | | | `--kong-admin-ca-cert-file` | `string` | Path to PEM-encoded CA certificate file to verify Kong's Admin TLS certificate. Mutually exclusive with --kong-admin-ca-cert. | | | `--kong-admin-concurrency` | `int` | Max number of concurrent requests sent to Kong's Admin API. | `10` | diff --git a/go.mod b/go.mod index 7140e40984..d203ca42a6 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.4.0 github.com/jpillora/backoff v1.0.0 - github.com/kong/go-database-reconciler v1.0.1 + github.com/kong/go-database-reconciler v1.1.0 github.com/kong/go-kong v0.48.0 github.com/kong/kubernetes-telemetry v0.1.2 github.com/kong/kubernetes-testing-framework v0.42.0 @@ -49,7 +49,7 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.26.0 go.uber.org/zap v1.26.0 - google.golang.org/api v0.151.0 + google.golang.org/api v0.152.0 k8s.io/api v0.28.4 k8s.io/apiextensions-apiserver v0.28.4 k8s.io/apimachinery v0.28.4 @@ -88,14 +88,14 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect go4.org/netipx v0.0.0-20230728184502-ec4c8b891b28 // indirect golang.org/x/net v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect k8s.io/klog/v2 v2.100.1 // indirect ) require ( - cloud.google.com/go/compute v1.23.1 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Kong/go-diff v1.2.2 // indirect @@ -200,11 +200,11 @@ require ( golang.org/x/sys v0.14.0 // indirect golang.org/x/term v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 6194247b1b..0f1e2f02f4 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0= -cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/container v1.29.0 h1:jIltU529R2zBFvP8rhiG1mgeTcnT27KhU0H/1d6SQRg= @@ -242,8 +242,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kong/go-database-reconciler v1.0.1 h1:SB+zvLq+4a8cyGArL+pBTnlTT00FYTmjY/aZopguwtA= -github.com/kong/go-database-reconciler v1.0.1/go.mod h1:p8NvafqBSuMR9YNCOZ24aIeeajc145+biXpAaMExvpI= +github.com/kong/go-database-reconciler v1.1.0 h1:USCdsAj/7eh9sOOfbnvsOe4jw5k4+FSTD3okcTLIVqQ= +github.com/kong/go-database-reconciler v1.1.0/go.mod h1:p8NvafqBSuMR9YNCOZ24aIeeajc145+biXpAaMExvpI= github.com/kong/go-kong v0.48.0 h1:vK1OpoxO50qlKdwPfmx9ChvkTKRsoCCB3b3iHo1umLc= github.com/kong/go-kong v0.48.0/go.mod h1:qH4CEFqT83ywmu1TlMZX09clQH4B8/dX88CtT/jdv/E= github.com/kong/kubernetes-telemetry v0.1.2 h1:fxKdEbFQ+aGrh+3x0LIEgRmyQ4wP/ZWv8QucqTI4Jcs= @@ -547,8 +547,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -567,8 +567,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/api v0.151.0 h1:FhfXLO/NFdJIzQtCqjpysWwqKk8AzGWBUhMIx67cVDU= -google.golang.org/api v0.151.0/go.mod h1:ccy+MJ6nrYFgE3WgRx/AMXOxOmU8Q4hSa+jjibzhxcg= +google.golang.org/api v0.152.0 h1:t0r1vPnfMc260S2Ci+en7kfCZaLOPs5KI0sVV/6jZrY= +google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -576,12 +576,12 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= -google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= -google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/internal/dataplane/translator/subtranslator/ingress.go b/internal/dataplane/translator/subtranslator/ingress.go index b20700dd8b..635a51223b 100644 --- a/internal/dataplane/translator/subtranslator/ingress.go +++ b/internal/dataplane/translator/subtranslator/ingress.go @@ -58,14 +58,20 @@ var defaultHTTPIngressPathType = netv1.PathTypeImplementationSpecific const ( defaultHTTPPort = 80 defaultRetries = 5 - - // defaultServiceTimeout indicates the amount of time by default that we wait - // for connections to an underlying Kubernetes service to complete in the - // data-plane. The current value is based on a historical default that started - // in version 0 of the ingress controller. - defaultServiceTimeout = time.Second * 60 ) +// defaultServiceTimeoutKongFormat returns the defaultServiceTimeout in format +// expected by Kong (pointer to an integer representing milliseconds). +// +// defaultServiceTimeout indicates the amount of time by default that we wait +// for connections to an underlying Kubernetes service to complete in the +// data-plane. The current value is based on a historical default that started +// in version 0 of the ingress controller. +func defaultServiceTimeoutInKongFormat() *int { + const defaultServiceTimeout = time.Second * 60 + return kong.Int(int(defaultServiceTimeout.Milliseconds())) +} + // ----------------------------------------------------------------------------- // Ingress Translation - Private - Index // ----------------------------------------------------------------------------- @@ -194,9 +200,9 @@ func (m *ingressTranslationMeta) translateIntoKongStateService(kongServiceName s Port: kong.Int(defaultHTTPPort), Protocol: kong.String("http"), Path: kong.String("/"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), Retries: kong.Int(defaultRetries), }, Backends: []kongstate.ServiceBackend{{ diff --git a/internal/dataplane/translator/subtranslator/ingress_atc_test.go b/internal/dataplane/translator/subtranslator/ingress_atc_test.go index 43cf02dd61..78280f85c0 100644 --- a/internal/dataplane/translator/subtranslator/ingress_atc_test.go +++ b/internal/dataplane/translator/subtranslator/ingress_atc_test.go @@ -58,13 +58,13 @@ func TestTranslateIngressATC(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -135,13 +135,13 @@ func TestTranslateIngressATC(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -217,13 +217,13 @@ func TestTranslateIngressATC(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ diff --git a/internal/dataplane/translator/subtranslator/ingress_test.go b/internal/dataplane/translator/subtranslator/ingress_test.go index f2405c9e58..ad5858fcf4 100644 --- a/internal/dataplane/translator/subtranslator/ingress_test.go +++ b/internal/dataplane/translator/subtranslator/ingress_test.go @@ -78,13 +78,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -151,13 +151,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -225,13 +225,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -299,13 +299,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -373,13 +373,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -446,13 +446,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -519,13 +519,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -657,13 +657,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -801,13 +801,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -894,13 +894,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service1.80"), Host: kong.String("test-service1.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{ { @@ -937,13 +937,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service2.80"), Host: kong.String("test-service2.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{ { @@ -1037,13 +1037,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.ad-service.80"), Host: kong.String("ad-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{ { @@ -1080,13 +1080,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.mad-service.80"), Host: kong.String("mad-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{ { @@ -1155,13 +1155,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.80"), Host: kong.String("test-service.default.80.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ @@ -1231,13 +1231,13 @@ func TestTranslateIngress(t *testing.T) { Service: kong.Service{ Name: kong.String("default.test-service.http"), Host: kong.String("test-service.default.http.svc"), - ConnectTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ConnectTimeout: defaultServiceTimeoutInKongFormat(), Path: kong.String("/"), Port: kong.Int(80), Protocol: kong.String("http"), Retries: kong.Int(defaultRetries), - ReadTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), - WriteTimeout: kong.Int(int(defaultServiceTimeout.Milliseconds())), + ReadTimeout: defaultServiceTimeoutInKongFormat(), + WriteTimeout: defaultServiceTimeoutInKongFormat(), }, Routes: []kongstate.Route{{ Ingress: util.K8sObjectInfo{ diff --git a/internal/manager/config.go b/internal/manager/config.go index 56be949d37..bcac753940 100644 --- a/internal/manager/config.go +++ b/internal/manager/config.go @@ -197,6 +197,7 @@ func (c *Config) FlagSet() *pflag.FlagSet { flagSet.StringVar(&c.ProbeAddr, "health-probe-bind-address", fmt.Sprintf(":%v", HealthzPort), "The address the probe endpoint binds to.") flagSet.Float32Var(&c.ProxySyncSeconds, "proxy-sync-seconds", dataplane.DefaultSyncSeconds, "Define the rate (in seconds) in which configuration updates will be applied to the Kong Admin API.") + flagSet.DurationVar(&c.InitCacheSyncDuration, "init-cache-sync-duration", dataplane.DefaultCacheSyncWaitDuration, `The initial delay to wait for Kubernetes object caches to be synced before the initial configuration.`) flagSet.Float32Var(&c.ProxyTimeoutSeconds, "proxy-timeout-seconds", dataplane.DefaultTimeoutSeconds, "Sets the timeout (in seconds) for all requests to Kong's Admin API.") diff --git a/test/integration/consts/consts.go b/test/integration/consts/consts.go index 96b85bc410..a91d658797 100644 --- a/test/integration/consts/consts.go +++ b/test/integration/consts/consts.go @@ -8,4 +8,7 @@ const ( // IngressWait is the default amount of time to wait for any particular ingress resource to be provisioned. IngressWait = 3 * time.Minute + + // StatusWait is the default amount of time to wait for object statuses to fulfill a provided predicate. + StatusWait = 3 * time.Minute ) diff --git a/test/integration/consts_test.go b/test/integration/consts_test.go index 602b7c12a2..1c3fe1b006 100644 --- a/test/integration/consts_test.go +++ b/test/integration/consts_test.go @@ -22,5 +22,5 @@ const ( // statusWait is a const duration used in test assertions like .Eventually to // wait for object statuses to fulfill a provided predicate. - statusWait = time.Minute * 3 + statusWait = consts.StatusWait ) diff --git a/test/integration/ingress_test.go b/test/integration/ingress_test.go index 6e2852cf55..9fbdcea62d 100644 --- a/test/integration/ingress_test.go +++ b/test/integration/ingress_test.go @@ -193,52 +193,6 @@ func TestIngressDefaultBackend(t *testing.T) { ) } -func TestGRPCIngressEssentials(t *testing.T) { - t.Parallel() - - ctx := context.Background() - ns, cleaner := helpers.Setup(ctx, t, env) - - t.Log("deploying a minimal HTTP container deployment to test Ingress routes") - container := generators.NewContainer("grpcbin", test.GRPCBinImage, test.GRPCBinPort) - deployment := generators.NewDeploymentForContainer(container) - deployment, err := env.Cluster().Client().AppsV1().Deployments(ns.Name).Create(ctx, deployment, metav1.CreateOptions{}) - require.NoError(t, err) - cleaner.Add(deployment) - - t.Logf("exposing deployment %s via service", deployment.Name) - service := generators.NewServiceForDeployment(deployment, corev1.ServiceTypeLoadBalancer) - // as of KTF 0.9,0 NewServiceForDeployment doesn't initialize annotations itself, need to do it outside - service.ObjectMeta.Annotations = map[string]string{annotations.AnnotationPrefix + annotations.ProtocolKey: "grpc"} - service, err = env.Cluster().Client().CoreV1().Services(ns.Name).Create(ctx, service, metav1.CreateOptions{}) - require.NoError(t, err) - cleaner.Add(service) - - t.Logf("creating an ingress for service %s with ingress.class %s", service.Name, consts.IngressClass) - ingress := generators.NewIngressForService("/", map[string]string{ - annotations.AnnotationPrefix + annotations.ProtocolsKey: "grpc,grpcs", - annotations.AnnotationPrefix + annotations.StripPathKey: "false", - }, service) - ingress.Spec.IngressClassName = kong.String(consts.IngressClass) - require.NoError(t, clusters.DeployIngress(ctx, env.Cluster(), ns.Name, ingress)) - cleaner.Add(ingress) - - t.Log("waiting for updated ingress status to include IP") - require.Eventually(t, func() bool { - lbstatus, err := clusters.GetIngressLoadbalancerStatus(ctx, env.Cluster(), ns.Name, ingress) - if err != nil { - return false - } - return len(lbstatus.Ingress) > 0 - }, statusWait, waitTick) - - // So far this only tests that the ingress is created and receives status information, to confirm the fix for - // https://github.com/Kong/kubernetes-ingress-controller/issues/1991 - // It does not test routing, though the status implementation implies it (we only add status after we confirm - // configuration is present in the proxy). This test could be expanded to better confirm routing with a suitable - // gRPC test client. -} - func TestIngressClassNameSpec(t *testing.T) { t.Parallel() t.Log("locking IngressClass management") diff --git a/test/integration/isolated/ctx.go b/test/integration/isolated/ctx.go index 2d8b90f274..8d331b5d26 100644 --- a/test/integration/isolated/ctx.go +++ b/test/integration/isolated/ctx.go @@ -139,3 +139,14 @@ func GetAdminURLFromCtx(ctx context.Context) *url.URL { } return u.(*url.URL) } + +type _ingressClass struct{} + +// GetIngressClassFromCtx gets the Ingress Class from the context. +func GetIngressClassFromCtx(ctx context.Context) string { + r := ctx.Value(_ingressClass{}) + if r == nil { + return "" + } + return r.(string) +} diff --git a/test/integration/isolated/ingress_test.go b/test/integration/isolated/ingress_test.go new file mode 100644 index 0000000000..ff8ed1b777 --- /dev/null +++ b/test/integration/isolated/ingress_test.go @@ -0,0 +1,198 @@ +//go:build integration_tests + +package isolated + +import ( + "context" + "fmt" + "testing" + + "github.com/google/uuid" + "github.com/kong/kubernetes-testing-framework/pkg/clusters" + ktfkong "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/kong" + "github.com/kong/kubernetes-testing-framework/pkg/utils/kubernetes/generators" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + netv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + "github.com/kong/kubernetes-ingress-controller/v3/internal/annotations" + "github.com/kong/kubernetes-ingress-controller/v3/internal/util/builder" + "github.com/kong/kubernetes-ingress-controller/v3/test" + "github.com/kong/kubernetes-ingress-controller/v3/test/helpers/certificate" + "github.com/kong/kubernetes-ingress-controller/v3/test/integration/consts" + "github.com/kong/kubernetes-ingress-controller/v3/test/internal/testlabels" +) + +func TestIngressGRPC(t *testing.T) { + const testHostname = "grpcs-over-ingress.example" + + f := features. + New("essentials"). + WithLabel(testlabels.NetworkingFamily, testlabels.NetworkingFamilyIngress). + WithLabel(testlabels.Kind, testlabels.KindIngress). + WithSetup("deploy kong addon into cluster", featureSetup( + withKongProxyEnvVars(map[string]string{ + "PROXY_LISTEN": `0.0.0.0:8000 http2\, 0.0.0.0:8443 http2 ssl`, + }), + )). + WithSetup("deploying gRPC service exposed via Ingress", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { + cleaner := GetFromCtxForT[*clusters.Cleaner](ctx, t) + cluster := GetClusterFromCtx(ctx) + namespace := GetNamespaceForT(ctx, t) + + t.Log("configuring secret") + tlsRouteExampleTLSCert, tlsRouteExampleTLSKey := certificate.MustGenerateSelfSignedCertPEMFormat(certificate.WithCommonName(testHostname)) + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "secret-test", + }, + Data: map[string][]byte{ + "tls.crt": tlsRouteExampleTLSCert, + "tls.key": tlsRouteExampleTLSKey, + }, + } + + t.Log("deploying secret") + secret, err := cluster.Client().CoreV1().Secrets(namespace).Create(ctx, secret, metav1.CreateOptions{}) + assert.NoError(t, err) + cleaner.Add(secret) + + type kongProtocolAnnotation string + const ( + gRPC kongProtocolAnnotation = "grpc" + gRPCS kongProtocolAnnotation = "grpcs" + ) + const ( + gRPCBinPort int32 = 9000 + gRPCSBinPort int32 = 9001 + ) + t.Log("deploying a minimal gRPC container deployment to test Ingress routes") + container := generators.NewContainer("grpcbin", test.GRPCBinImage, 0) + // Overwrite ports to specify gRPC over HTTP (9000) and gRPC over HTTPS (9001). + container.Ports = []corev1.ContainerPort{{ContainerPort: gRPCBinPort, Name: string(gRPC)}, {ContainerPort: gRPCSBinPort, Name: string(gRPCS)}} + deployment := generators.NewDeploymentForContainer(container) + deployment, err = cluster.Client().AppsV1().Deployments(namespace).Create(ctx, deployment, metav1.CreateOptions{}) + assert.NoError(t, err) + cleaner.Add(deployment) + + exposeWithService := func(p kongProtocolAnnotation) *corev1.Service { + grpcBinPort := gRPCBinPort + if p == gRPCS { + grpcBinPort = gRPCSBinPort + } + kongProtocol := string(p) + t.Logf("exposing deployment gRPC (%s) port %s via service", kongProtocol, deployment.Name) + svc := generators.NewServiceForDeploymentWithMappedPorts(deployment, corev1.ServiceTypeLoadBalancer, map[int32]int32{grpcBinPort: grpcBinPort}) + svc.Name += kongProtocol + svc.Annotations = map[string]string{ + annotations.AnnotationPrefix + annotations.ProtocolKey: kongProtocol, + } + _, err = cluster.Client().CoreV1().Services(namespace).Create(ctx, svc, metav1.CreateOptions{}) + assert.NoError(t, err) + cleaner.Add(svc) + return svc + } + + // Deploy two services, one for gRPC and one for gRPCS. Two protocols in one service annotation (konghq.com/protocol) are not supported. + serviceGRPC := exposeWithService(gRPC) + serviceGRPCS := exposeWithService(gRPCS) + + ingressClass := GetIngressClassFromCtx(ctx) + t.Logf("creating an ingress for services: %s, %s with ingress.class %s", serviceGRPC.Name, serviceGRPCS.Name, ingressClass) + ingress := builder.NewIngress(uuid.NewString(), ingressClass).WithRules( + netv1.IngressRule{ + Host: testHostname, + IngressRuleValue: netv1.IngressRuleValue{ + HTTP: &netv1.HTTPIngressRuleValue{ + Paths: []netv1.HTTPIngressPath{ + { + Path: "/", + PathType: lo.ToPtr(netv1.PathTypePrefix), + Backend: netv1.IngressBackend{ + Service: &netv1.IngressServiceBackend{ + Name: serviceGRPCS.Name, + Port: netv1.ServiceBackendPort{ + Number: gRPCSBinPort, + }, + }, + }, + }, + }, + }, + }, + }, + netv1.IngressRule{ + IngressRuleValue: netv1.IngressRuleValue{ + HTTP: &netv1.HTTPIngressRuleValue{ + Paths: []netv1.HTTPIngressPath{ + { + Path: "/", + PathType: lo.ToPtr(netv1.PathTypePrefix), + Backend: netv1.IngressBackend{ + Service: &netv1.IngressServiceBackend{ + Name: serviceGRPC.Name, + Port: netv1.ServiceBackendPort{ + Number: gRPCBinPort, + }, + }, + }, + }, + }, + }, + }, + }, + ).Build() + ingress.Annotations[annotations.AnnotationPrefix+annotations.ProtocolsKey] = fmt.Sprintf("%s,%s", gRPC, gRPCS) + assert.NoError(t, clusters.DeployIngress(ctx, cluster, namespace, ingress)) + cleaner.Add(ingress) + ctx = SetInCtxForT(ctx, t, ingress) + + return ctx + }). + Assess("checking whether Ingress status is updated and gRPC traffic over HTTPS is properly routed", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { + t.Log("waiting for updated ingress status to include IP") + assert.Eventually(t, func() bool { + cluster := GetClusterFromCtx(ctx) + namespace := GetNamespaceForT(ctx, t) + ingress := GetFromCtxForT[*netv1.Ingress](ctx, t) + + lbstatus, err := clusters.GetIngressLoadbalancerStatus(ctx, cluster, namespace, ingress) + if err != nil { + return false + } + return len(lbstatus.Ingress) > 0 + }, consts.StatusWait, consts.WaitTick) + + verifyEchoResponds := func(hostname string) { + // Kong Gateway uses different ports for HTTP and HTTPS traffic. + proxyPort := ktfkong.DefaultProxyTLSServicePort + tlsEnabled := true + if hostname == "" { + proxyPort = ktfkong.DefaultProxyHTTPPort + tlsEnabled = false + } + assert.Eventually(t, func() bool { + if err := grpcEchoResponds( + ctx, fmt.Sprintf("%s:%d", GetProxyURLFromCtx(ctx).Hostname(), proxyPort), hostname, "echo Kong", tlsEnabled, + ); err != nil { + t.Log(err) + return false + } + return true + }, consts.IngressWait, consts.WaitTick) + } + t.Log("verifying service connectivity via HTTPS (gRPCS)") + verifyEchoResponds(testHostname) + t.Log("verifying service connectivity via HTTP (gRPC)") + verifyEchoResponds("") + + return ctx + }). + Teardown(featureTeardown()) + + tenv.Test(t, f.Feature()) +} diff --git a/test/integration/isolated/suite_test.go b/test/integration/isolated/suite_test.go index edf670b601..d66271e9af 100644 --- a/test/integration/isolated/suite_test.go +++ b/test/integration/isolated/suite_test.go @@ -329,6 +329,7 @@ func featureSetup(opts ...featureSetupOpt) func(ctx context.Context, t *testing. // the cleaner always gets a 404 on it for unknown reasons _ = cluster.Client().NetworkingV1().IngressClasses().Delete(ctx, ingressClass, metav1.DeleteOptions{}) }() + ctx = setInCtx(ctx, _ingressClass{}, ingressClass) clusterVersion, err := cluster.Version() if !assert.NoError(t, err, "failed getting cluster version") { diff --git a/test/internal/testlabels/labels.go b/test/internal/testlabels/labels.go index 3a2f3f123c..aa2d5a0719 100644 --- a/test/internal/testlabels/labels.go +++ b/test/internal/testlabels/labels.go @@ -5,6 +5,7 @@ const ( Kind = "kind" KindUDPRoute = "UDPRoute" KindGRPCRoute = "GRPCRoute" + KindIngress = "Ingress" ) const (