Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(conformance): tls conformance test enabled #3797

Closed
wants to merge 10 commits into from
Closed
24 changes: 14 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Adding a new version? You'll need three changes:
[#4211](https://github.com/Kong/kubernetes-ingress-controller/pull/4211)
- Assign priorities to routes translated from Ingresses when parser translate
them to expression based Kong routes. The assigning method is basically the
same as in Kong gateway's `traditional_compatible` router, except that
same as in Kong gateway's `traditional_compatible` router, except that
`regex_priority` field in Kong traditional route is not supported. This
method is adopted to keep the compatibility with traditional router on
maximum effort.
Expand All @@ -148,7 +148,7 @@ Adding a new version? You'll need three changes:
[specification on priorities of matches in `HTTPRoute`][httproute-specification].
[#4296](https://github.com/Kong/kubernetes-ingress-controller/pull/4296)
[#4434](https://github.com/Kong/kubernetes-ingress-controller/pull/4434)
- Assign priorities to routes translated from GRPCRoutes when the parser translates
- Assign priorities to routes translated from GRPCRoutes when the parser translates
them to expression based Kong routes. The priority order follows the
[specification on match priorities in GRPCRoute][grpcroute-specification].
[#4364](https://github.com/Kong/kubernetes-ingress-controller/pull/4364)
Expand All @@ -165,10 +165,11 @@ Adding a new version? You'll need three changes:
in terms of accepting data-plane traffic, but are ready to accept configuration
updates. The controller will now send configuration to such Gateways and will
actively monitor their readiness for accepting configuration updates.
[#4368](https://github.com/Kong/kubernetes-ingress-controller/pull/4368
- `KongConsumer`, `KongConsumerGroup` `KongPlugin`, and `KongClusterPlugin` CRDs were extended with
`Status.Conditions` field. It will contain the `Programmed` condition describing
whether an object was successfully translated into Kong entities and sent to Kong.
[#4368](https://github.com/Kong/kubernetes-ingress-controller/pull/4368)
- `KongConsumer`, `KongConsumerGroup` `KongPlugin`, and `KongClusterPlugin` CRDs
were extended with `Status.Conditions` field. It will contain the `Programmed`
condition describing whether an object was successfully translated into Kong
entities and sent to Kong.
[#4409](https://github.com/Kong/kubernetes-ingress-controller/pull/4409)
[#4412](https://github.com/Kong/kubernetes-ingress-controller/pull/4412)
[#4423](https://github.com/Kong/kubernetes-ingress-controller/pull/4423)
Expand All @@ -182,6 +183,9 @@ Adding a new version? You'll need three changes:
in the `Programmed` condition of the object being set to `False` and an
event being emitted.
[#4428](https://github.com/Kong/kubernetes-ingress-controller/pull/4428)
- A new `--publish-service-tls` flag has been added to expose Kong TLS stream port
(default value is 8899) through a service using a different port.
[#3797](https://github.com/Kong/kubernetes-ingress-controller/pull/3797)

### Changed

Expand All @@ -200,11 +204,11 @@ Adding a new version? You'll need three changes:
- Changed the Gateway's readiness probe in all-in-one manifests from `/status`
to `/status/ready`. Gateways will be considered ready only after an initial
configuration is applied by the controller.
[#4368](https://github.com/Kong/kubernetes-ingress-controller/pull/4368
- When translating to expression based Kong routes, annotations to specify
[#4368](https://github.com/Kong/kubernetes-ingress-controller/pull/4368)
- When translating to expression based Kong routes, annotations to specify
protocols are translated to `protocols` field of the result Kong route,
instead of putting the conditions to match protocols inside expressions.
[#4422](https://github.com/Kong/kubernetes-ingress-controller/pull/4422)
instead of putting the conditions to match protocols inside expressions.
[#4422](https://github.com/Kong/kubernetes-ingress-controller/pull/4422)

### Fixed

Expand Down
48 changes: 36 additions & 12 deletions internal/controllers/gateway/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type GatewayReconciler struct { //nolint:revive

PublishServiceRef k8stypes.NamespacedName
PublishServiceUDPRef mo.Option[k8stypes.NamespacedName]
PublishServiceTLSRef mo.Option[k8stypes.NamespacedName]

// If enableReferenceGrant is true, controller will watch ReferenceGrants
// to invalidate or allow cross-namespace TLSConfigs in gateways.
Expand Down Expand Up @@ -451,6 +452,11 @@ func (r *GatewayReconciler) reconcileUnmanagedGateway(ctx context.Context, log l
services = append(services, udpRef.String())
}

// TLS service is optional.
if tlsRef, ok := r.PublishServiceTLSRef.Get(); ok {
services = append(services, tlsRef.String())
}

servicesAnnotation := strings.Join(services, ",")
debug(log, gateway, fmt.Sprintf("no unmanaged annotation, setting it to proxy services %s", services))
if gateway.Annotations == nil {
Expand All @@ -461,19 +467,24 @@ func (r *GatewayReconciler) reconcileUnmanagedGateway(ctx context.Context, log l
}

serviceRefs := strings.Split(annotations.ExtractUnmanagedGatewayClassMode(gateway.Annotations), ",")

// validation check of the Gateway to ensure that the publish service is actually available
// in the cluster. If it is not the object will be requeued until it exists (or is otherwise retrievable).
debug(log, gateway, "gathering the gateway publish service") // this will also be done by the validating webhook, this is a fallback

var gatewayServices []*corev1.Service
for _, ref := range serviceRefs {
r.Log.V(util.DebugLevel).Info("determining service for ref", "ref", ref)
svc, err := r.determineServiceForGateway(ctx, ref)
if err != nil {
log.Error(err, "could not determine service for gateway", "namespace", gateway.Namespace, "name", gateway.Name)
return ctrl.Result{Requeue: true}, err
}
if svc != nil {
gatewayServices = append(gatewayServices, svc)

for _, l := range gateway.Spec.Listeners {
svc, err := r.determineServiceForGateway(ctx, ref, l.Protocol)
if err != nil {
log.Error(err, "could not determine service for gateway", "namespace", gateway.Namespace, "name", gateway.Name)
return ctrl.Result{Requeue: true}, err
}
if svc != nil {
gatewayServices = append(gatewayServices, svc)
}
}
}

Expand Down Expand Up @@ -609,20 +620,31 @@ func init() {

// determineServiceForGateway provides the "publish service" (aka the proxy Service) object which
// will be used to populate unmanaged gateways.
func (r *GatewayReconciler) determineServiceForGateway(ctx context.Context, ref string) (*corev1.Service, error) {
func (r *GatewayReconciler) determineServiceForGateway(ctx context.Context, ref string, protocol gatewayv1beta1.ProtocolType) (*corev1.Service, error) {
// currently the gateway controller ONLY supports service references that correspond with the --publish-service
// provided to the controller manager via flags when operating on unmanaged gateways. This constraint may
// be loosened in later iterations if there is need.

var name k8stypes.NamespacedName
switch {
case ref == r.PublishServiceRef.String():
name = r.PublishServiceRef
if protocol == gatewayv1beta1.HTTPProtocolType ||
protocol == gatewayv1beta1.HTTPSProtocolType ||
protocol == gatewayv1beta1.TCPProtocolType ||
r.PublishServiceTLSRef.IsAbsent() && protocol == TLSProtocolType {
name = r.PublishServiceRef
}
case r.PublishServiceUDPRef.IsPresent() && ref == r.PublishServiceUDPRef.MustGet().String():
name = r.PublishServiceUDPRef.MustGet()
if protocol == gatewayv1beta1.UDPProtocolType {
name = r.PublishServiceUDPRef.MustGet()
}
case r.PublishServiceTLSRef.IsPresent() && ref == r.PublishServiceTLSRef.MustGet().String():
if protocol == gatewayv1beta1.TLSProtocolType {
name = r.PublishServiceTLSRef.MustGet()
}
default:
return nil, fmt.Errorf("service ref %s did not match controller manager ref %s or %s",
ref, r.PublishServiceRef.String(), r.PublishServiceUDPRef.OrEmpty())
return nil, fmt.Errorf("service ref %s did not match controller manager ref %s, %s or %s",
ref, r.PublishServiceRef.String(), r.PublishServiceUDPRef.OrEmpty(), r.PublishServiceTLSRef.OrEmpty())
}

// retrieve the service for the kong gateway
Expand Down Expand Up @@ -757,6 +779,8 @@ func (r *GatewayReconciler) determineListenersFromDataPlane(
{Group: &gatewayV1beta1Group, Kind: (Kind)("TLSRoute")},
},
}
upgradedListeners = append(upgradedListeners, listener)
continue
}
}
if proxyListener, ok := proxyListenersMap[portMapper[int(listener.Port)]]; ok {
Expand Down
4 changes: 4 additions & 0 deletions internal/manager/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type Config struct {

// Ingress status
PublishServiceUDP OptionalNamespacedName
PublishServiceTLS OptionalNamespacedName
PublishService OptionalNamespacedName
PublishStatusAddress []string
PublishStatusAddressUDP []string
Expand Down Expand Up @@ -209,6 +210,9 @@ func (c *Config) FlagSet() *pflag.FlagSet {
flagSet.Var(flags.NewValidatedValue(&c.PublishServiceUDP, namespacedNameFromFlagValue, nnTypeNameOverride), "publish-service-udp", `Service fronting UDP routing resources in `+
`"namespace/name" format. The controller will update UDP route status information with this Service's `+
`endpoints. If omitted, the same Service will be used for both TCP and UDP routes.`)
flagSet.Var(flags.NewValidatedValue(&c.PublishServiceTLS, namespacedNameFromFlagValue, nnTypeNameOverride), "publish-service-tls", `Optional Service for TLS Gateway Listeners in `+
`"namespace/name" format. When omitted, TLS Listeners use the --publish-service Service.`+
`Only necessary if TLS and HTTPS Listeners share the same port.`)
flagSet.StringSliceVar(&c.PublishStatusAddressUDP, "publish-status-address-udp", []string{},
`User-provided address CSV, for use in lieu of "publish-service-udp" when that Service lacks useful address information.`)

Expand Down
1 change: 1 addition & 0 deletions internal/manager/controllerdef.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ func setupControllers(
DataplaneClient: dataplaneClient,
PublishServiceRef: c.PublishService.OrEmpty(),
PublishServiceUDPRef: c.PublishServiceUDP,
PublishServiceTLSRef: c.PublishServiceTLS,
WatchNamespaces: c.WatchNamespaces,
CacheSyncTimeout: c.CacheSyncTimeout,
ReferenceIndexers: referenceIndexers,
Expand Down
36 changes: 33 additions & 3 deletions test/conformance/gateway_conformance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ package conformance

import (
"fmt"
"strings"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
Expand Down Expand Up @@ -39,7 +42,7 @@ var skippedTestsForExpressionRoutes = []string{
tests.HTTPRouteRedirectPortAndScheme.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3680
tests.GatewayClassObservedGenerationBump.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3678
// https://github.com/Kong/kubernetes-ingress-controller/issues/4312
rainest marked this conversation as resolved.
Show resolved Hide resolved
tests.TLSRouteSimpleSameNamespace.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3679
tests.HTTPRouteQueryParamMatching.ShortName,
Expand Down Expand Up @@ -74,8 +77,6 @@ var skippedTestsForTraditionalRoutes = []string{
tests.HTTPRouteRedirectPortAndScheme.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3680
tests.GatewayClassObservedGenerationBump.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3678
tests.TLSRouteSimpleSameNamespace.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3679
tests.HTTPRouteQueryParamMatching.ShortName,
// https://github.com/Kong/kubernetes-ingress-controller/issues/3681
Expand All @@ -101,6 +102,34 @@ func TestGatewayConformance(t *testing.T) {
require.NoError(t, gatewayv1alpha2.AddToScheme(client.Scheme()))
require.NoError(t, gatewayv1beta1.AddToScheme(client.Scheme()))

// This service creation is a temporary solution, intended to be replaced by
// https://github.com/Kong/charts/issues/848
t.Log("creating tls service for gateway conformance tests")
svcNameSuffix, _, _ := strings.Cut(uuid.NewString(), "-")
tlsService := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-controller-kong-tls-proxy-" + svcNameSuffix,
Namespace: "kong",
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
"app.kubernetes.io/component": "app",
"app.kubernetes.io/instance": "ingress-controller",
"app.kubernetes.io/name": "kong",
},
Type: corev1.ServiceTypeLoadBalancer,
Ports: []corev1.ServicePort{
{
Port: 443,
TargetPort: intstr.FromInt(8899),
Protocol: corev1.ProtocolTCP,
},
},
},
}
require.NoError(t, client.Create(ctx, tlsService))
t.Cleanup(func() { assert.NoError(t, client.Delete(ctx, tlsService)) })

featureGateFlag := fmt.Sprintf("--feature-gates=%s", consts.DefaultFeatureGates)
if expressionRoutesEnabled() {
t.Log("expression routes enabled")
Expand All @@ -120,6 +149,7 @@ func TestGatewayConformance(t *testing.T) {
"--debug-log-reduce-redundancy",
featureGateFlag,
"--anonymous-reports=false",
fmt.Sprintf("--publish-service-tls=%s/%s", tlsService.Namespace, tlsService.Name),
}

require.NoError(t, testutils.DeployControllerManagerForCluster(ctx, globalDeprecatedLogger, globalLogger, env.Cluster(), args...))
Expand Down