Skip to content

Commit 373b12d

Browse files
authored
[Backport release/3.4.x] fix(translator): check gateway class and do not skip listeners when gateway class is not managed by KIC (#7718)
* fix(translator): check gateway class and do not skip listeners when gateway class is not managed by KIC (#7666) * check gateway class and do not skip listeners when gateway class is not managed by KIC * update changelog * store gatewayclass into cache in gwc controller * fix comments and move gwc controller name check after getting gwc (cherry picked from commit 2562662) * fix changelog
1 parent 709cefa commit 373b12d

File tree

14 files changed

+112
-19
lines changed

14 files changed

+112
-19
lines changed

CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ Adding a new version? You'll need three changes:
112112

113113
### Fixed
114114

115+
- Do not skip the gateway listeners without `Programmed` condition set to `True`
116+
when the gateway class does not contain `konghq.com/gateway-unmanaged`
117+
annotation in extracting certificates from listeners. This fixes the issue
118+
that KIC deletes the certificates of listeners on dataplane pods deleted when
119+
KIC is running under the control of Kong gateway operator.
120+
[#7666](https://github.com/Kong/kubernetes-ingress-controller/pull/7666)
115121
- Add `request-termination` plugin to return `500` if there are no available
116122
`backendRef` only when the service is translated from `HTTPRoute` or
117123
`GRPCRoute`.
@@ -4112,8 +4118,8 @@ Please read the changelog and test in your environment.
41124118
- The initial versions were rapildy iterated to deliver
41134119
a working ingress controller.
41144120

4115-
[3.4.6]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.7...v3.4.8
4116-
[3.4.5]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.6...v3.4.7
4121+
[3.4.8]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.7...v3.4.8
4122+
[3.4.7]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.6...v3.4.7
41174123
[3.4.6]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.5...v3.4.6
41184124
[3.4.5]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.4...v3.4.5
41194125
[3.4.4]: https://github.com/kong/kubernetes-ingress-controller/compare/v3.4.3...v3.4.4

hack/generators/cache-stores/spec.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ var supportedTypes = []cacheStoreSupportedType{
6060
Type: "Gateway",
6161
Package: "gatewayapi",
6262
},
63+
{
64+
Type: "GatewayClass",
65+
Package: "gatewayapi",
66+
KeyFunc: clusterWideKeyFunc,
67+
},
6368
{
6469
Type: "BackendTLSPolicy",
6570
Package: "gatewayapi",

internal/controllers/gateway/gateway_controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
143143
Log: r.Log.WithName(strings.ToUpper(gatewayapi.V1GroupVersion) + "GatewayClass"),
144144
Scheme: r.Scheme,
145145
CacheSyncTimeout: r.CacheSyncTimeout,
146+
147+
DataplaneClient: r.DataplaneClient,
146148
}
147149

148150
return gwcCTRL.SetupWithManager(mgr)
@@ -181,6 +183,7 @@ func (r *GatewayReconciler) gatewayHasMatchingGatewayClass(obj client.Object) bo
181183
r.Log.Error(err, "Could not retrieve gatewayclass", "gatewayclass", gateway.Spec.GatewayClassName)
182184
return false
183185
}
186+
184187
return isGatewayClassControlled(gatewayClass)
185188
}
186189

internal/controllers/gateway/gatewayclass_controller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"sigs.k8s.io/controller-runtime/pkg/predicate"
1919
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2020

21+
"github.com/kong/kubernetes-ingress-controller/v3/internal/controllers"
2122
"github.com/kong/kubernetes-ingress-controller/v3/internal/gatewayapi"
2223
"github.com/kong/kubernetes-ingress-controller/v3/internal/logging"
2324
"github.com/kong/kubernetes-ingress-controller/v3/internal/util"
@@ -59,6 +60,8 @@ type GatewayClassReconciler struct { //nolint:revive
5960
Log logr.Logger
6061
Scheme *runtime.Scheme
6162
CacheSyncTimeout time.Duration
63+
64+
DataplaneClient controllers.DataPlane
6265
}
6366

6467
// SetupWithManager sets up the controller with the Manager.
@@ -144,6 +147,13 @@ func (r *GatewayClassReconciler) Reconcile(ctx context.Context, req ctrl.Request
144147
setGatewayClassCondition(gwc, acceptedCondtion)
145148
return ctrl.Result{}, r.Status().Update(ctx, pruneGatewayClassStatusConds(gwc))
146149
}
150+
151+
// Add the gatewayclass to the translation cache if the gatewayclass is managed by the KIC instance.
152+
err := r.DataplaneClient.UpdateObject(gwc)
153+
if err != nil {
154+
debug(log, gwc, "Failed to update GatewayClass in dataplane, requeueing")
155+
return ctrl.Result{}, err
156+
}
147157
}
148158

149159
return ctrl.Result{}, nil

internal/dataplane/fallback/graph_dependencies.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ func ResolveDependencies(cache store.CacheStores, obj client.Object) ([]client.O
6262
*discoveryv1.EndpointSlice,
6363
*gatewayapi.ReferenceGrant,
6464
*gatewayapi.Gateway,
65+
*gatewayapi.GatewayClass,
6566
*gatewayapi.BackendTLSPolicy,
6667
*configurationv1.KongIngress,
6768
*configurationv1beta1.KongUpstreamPolicy,

internal/dataplane/kong_client_golden_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ func runKongClientGoldenTest(t *testing.T, tc kongClientGoldenTestCase) {
259259
// Create the translator.
260260
logger := zapr.NewLogger(zap.NewNop())
261261
s := store.New(cacheStores, "kong", logger)
262-
p, err := translator.NewTranslator(logger, s, "", tc.featureFlags, fakeSchemaServiceProvier{}, consts.DefaultClusterDomain)
262+
translatorConfig := translator.Config{
263+
ClusterDomain: consts.DefaultClusterDomain,
264+
}
265+
p, err := translator.NewTranslator(logger, s, "", tc.featureFlags, fakeSchemaServiceProvier{}, translatorConfig)
263266
require.NoError(t, err, "failed creating translator")
264267

265268
// Start a mock Admin API server and create an Admin API client for inspecting the configuration.

internal/dataplane/translator/translate_certs.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ import (
99

1010
"github.com/go-logr/logr"
1111
"github.com/kong/go-kong/kong"
12+
"github.com/samber/lo"
1213
corev1 "k8s.io/api/core/v1"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415

16+
"github.com/kong/kubernetes-ingress-controller/v3/internal/annotations"
1517
"github.com/kong/kubernetes-ingress-controller/v3/internal/dataplane/kongstate"
1618
"github.com/kong/kubernetes-ingress-controller/v3/internal/gatewayapi"
1719
"github.com/kong/kubernetes-ingress-controller/v3/internal/logging"
@@ -55,11 +57,21 @@ func (t *Translator) getGatewayCerts() []certWrapper {
5557
return certs
5658
}
5759
for _, gateway := range gateways {
58-
statuses := make(map[gatewayapi.SectionName]gatewayapi.ListenerStatus, len(gateway.Status.Listeners))
59-
for _, status := range gateway.Status.Listeners {
60-
statuses[status.Name] = status
60+
gwc, err := s.GetGatewayClass(string(gateway.Spec.GatewayClassName))
61+
if err != nil {
62+
logger.Error(err, "Failed to get GatewayClass for Gateway, skipping", "gateway", gateway.Name, "gateway_class", gateway.Spec.GatewayClassName)
63+
continue
6164
}
6265

66+
// Skip the gateway when the gateway's GatewayClass is not controlled by the KIC instance.
67+
if gwc.Spec.ControllerName != gatewayapi.GatewayController(t.gatewayControllerName) {
68+
continue
69+
}
70+
71+
statuses := lo.SliceToMap(gateway.Status.Listeners, func(status gatewayapi.ListenerStatus) (gatewayapi.SectionName, gatewayapi.ListenerStatus) {
72+
return status.Name, status
73+
})
74+
6375
for _, listener := range gateway.Spec.Listeners {
6476
status, ok := statuses[listener.Name]
6577
if !ok {
@@ -72,14 +84,18 @@ func (t *Translator) getGatewayCerts() []certWrapper {
7284
continue
7385
}
7486

75-
// Check if listener is marked as programmed
76-
if !util.CheckCondition(
77-
status.Conditions,
78-
util.ConditionType(gatewayapi.ListenerConditionProgrammed),
79-
util.ConditionReason(gatewayapi.ListenerReasonProgrammed),
80-
metav1.ConditionTrue,
81-
gateway.Generation,
82-
) {
87+
// Check if listener is marked as programmed when the gateway's GatewayClass has the "Unmanaged" annotation.
88+
// If the GatewayClass does not have the annotation, the gateway is considered to be managed by other components (for example Kong Operator),
89+
// so we do not check the "Programmed" condition before extracting the certificate from the listener
90+
// to prevent unexpected deletion of certificates when the instance is managed by Kong Operator.
91+
if annotations.ExtractUnmanagedGatewayClassMode(gwc.Annotations) != "" &&
92+
!util.CheckCondition(
93+
status.Conditions,
94+
util.ConditionType(gatewayapi.ListenerConditionProgrammed),
95+
util.ConditionReason(gatewayapi.ListenerReasonProgrammed),
96+
metav1.ConditionTrue,
97+
gateway.Generation,
98+
) {
8399
continue
84100
}
85101

internal/dataplane/translator/translator.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,18 @@ type Translator struct {
105105
failuresCollector *failures.ResourceFailuresCollector
106106
translatedObjectsCollector *ObjectsCollector
107107

108-
clusterDomain string
108+
clusterDomain string
109+
gatewayControllerName string
110+
}
111+
112+
// Config is a configuration for the Translator.
113+
type Config struct {
114+
// ClusterDomain is the cluster domain used for translating Kubernetes objects.
115+
ClusterDomain string
116+
117+
// GatewayControllerName is the gateway controller name used by KIC.
118+
// GatewayClasses with this controller name in spec.ControllerName are managed by KIC, otherwise they are managed by other (like Kong Operator).
119+
GatewayControllerName string
109120
}
110121

111122
// NewTranslator produces a new Translator object provided a logging mechanism
@@ -116,7 +127,7 @@ func NewTranslator(
116127
workspace string,
117128
featureFlags FeatureFlags,
118129
schemaServiceProvider SchemaServiceProvider,
119-
clusterDomain string,
130+
config Config,
120131
) (*Translator, error) {
121132
failuresCollector := failures.NewResourceFailuresCollector(logger)
122133

@@ -134,7 +145,8 @@ func NewTranslator(
134145
schemaServiceProvider: schemaServiceProvider,
135146
failuresCollector: failuresCollector,
136147
translatedObjectsCollector: translatedObjectsCollector,
137-
clusterDomain: clusterDomain,
148+
clusterDomain: config.ClusterDomain,
149+
gatewayControllerName: config.GatewayControllerName,
138150
}, nil
139151
}
140152

internal/dataplane/translator/translator_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5103,6 +5103,9 @@ func (p fakeSchemaServiceProvier) GetSchemaService() kong.AbstractSchemaService
51035103

51045104
func mustNewTranslator(t *testing.T, storer store.Storer) *Translator {
51055105
logger := zapr.NewLogger(zap.NewNop())
5106+
translatorConfig := Config{
5107+
ClusterDomain: consts.DefaultClusterDomain,
5108+
}
51065109
p, err := NewTranslator(logger, storer, "",
51075110
FeatureFlags{
51085111
// We'll assume these are true for all tests.
@@ -5111,7 +5114,7 @@ func mustNewTranslator(t *testing.T, storer store.Storer) *Translator {
51115114
KongServiceFacade: true,
51125115
},
51135116
fakeSchemaServiceProvier{},
5114-
consts.DefaultClusterDomain,
5117+
translatorConfig,
51155118
)
51165119
require.NoError(t, err)
51175120
return p

internal/manager/run.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,12 @@ func New(
210210
cache := store.NewCacheStores()
211211
storer := store.New(cache, c.IngressClassName, logger)
212212

213-
configTranslator, err := translator.NewTranslator(logger, storer, c.KongWorkspace, translatorFeatureFlags, NewSchemaServiceGetter(clientsManager), c.ClusterDomain)
213+
configTranslator, err := translator.NewTranslator(logger, storer, c.KongWorkspace, translatorFeatureFlags, NewSchemaServiceGetter(clientsManager),
214+
translator.Config{
215+
ClusterDomain: c.ClusterDomain,
216+
GatewayControllerName: c.GatewayAPIControllerName,
217+
},
218+
)
214219
if err != nil {
215220
return nil, fmt.Errorf("failed to create translator: %w", err)
216221
}

0 commit comments

Comments
 (0)