Skip to content

Commit e61d276

Browse files
authored
feat: skip setup gateway api related controllers when cluster not support (#215)
Signed-off-by: Ashing Zheng <[email protected]>
1 parent b83fd8e commit e61d276

File tree

4 files changed

+115
-17
lines changed

4 files changed

+115
-17
lines changed

.github/workflows/apisix-conformance-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
ARCH: amd64
8787
ENABLE_PROXY: "false"
8888
BASE_IMAGE_TAG: "debug"
89-
ADC_VERSION: "dev"
89+
# ADC_VERSION: "dev"
9090
run: |
9191
echo "building images..."
9292
make build-image

.github/workflows/apisix-e2e-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
ARCH: amd64
8787
ENABLE_PROXY: "false"
8888
BASE_IMAGE_TAG: "debug"
89-
ADC_VERSION: "dev"
89+
# ADC_VERSION: "dev"
9090
run: |
9191
echo "building images..."
9292
make build-image

internal/manager/controllers.go

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/apache/apisix-ingress-controller/internal/manager/readiness"
3838
"github.com/apache/apisix-ingress-controller/internal/provider"
3939
types "github.com/apache/apisix-ingress-controller/internal/types"
40+
"github.com/apache/apisix-ingress-controller/pkg/utils"
4041
)
4142

4243
// K8s
@@ -97,40 +98,55 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
9798
if err := indexer.SetupIndexer(mgr); err != nil {
9899
return nil, err
99100
}
100-
return []Controller{
101-
&controller.GatewayClassReconciler{
101+
102+
setupLog := ctrl.LoggerFrom(ctx).WithName("setup")
103+
var controllers []Controller
104+
105+
// Gateway API Controllers - conditional registration based on API availability
106+
for resource, controller := range map[client.Object]Controller{
107+
&gatewayv1.GatewayClass{}: &controller.GatewayClassReconciler{
102108
Client: mgr.GetClient(),
103109
Scheme: mgr.GetScheme(),
104110
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayClass"),
105111
Updater: updater,
106112
},
107-
&controller.GatewayReconciler{
113+
&gatewayv1.Gateway{}: &controller.GatewayReconciler{
108114
Client: mgr.GetClient(),
109115
Scheme: mgr.GetScheme(),
110116
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Gateway"),
111117
Provider: pro,
112118
Updater: updater,
113119
},
114-
&controller.HTTPRouteReconciler{
120+
&gatewayv1.HTTPRoute{}: &controller.HTTPRouteReconciler{
115121
Client: mgr.GetClient(),
116122
Scheme: mgr.GetScheme(),
117123
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("HTTPRoute"),
118124
Provider: pro,
119125
Updater: updater,
120126
Readier: readier,
121127
},
122-
&controller.IngressReconciler{
128+
&v1alpha1.Consumer{}: &controller.ConsumerReconciler{
123129
Client: mgr.GetClient(),
124130
Scheme: mgr.GetScheme(),
125-
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Ingress"),
131+
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Consumer"),
126132
Provider: pro,
127133
Updater: updater,
128134
Readier: readier,
129135
},
130-
&controller.ConsumerReconciler{
136+
} {
137+
if utils.HasAPIResource(mgr, resource) {
138+
controllers = append(controllers, controller)
139+
} else {
140+
setupLog.Info("Skipping controller setup, API not found in cluster", "api", utils.FormatGVK(resource))
141+
}
142+
}
143+
144+
controllers = append(controllers, []Controller{
145+
// Core Kubernetes Controllers - always register these
146+
&controller.IngressReconciler{
131147
Client: mgr.GetClient(),
132148
Scheme: mgr.GetScheme(),
133-
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Consumer"),
149+
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Ingress"),
134150
Provider: pro,
135151
Updater: updater,
136152
Readier: readier,
@@ -141,6 +157,14 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
141157
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("IngressClass"),
142158
Provider: pro,
143159
},
160+
// Gateway Proxy Controller - always register this as it is core to the controller
161+
&controller.GatewayProxyController{
162+
Client: mgr.GetClient(),
163+
Scheme: mgr.GetScheme(),
164+
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayProxy"),
165+
Provider: pro,
166+
},
167+
// APISIX v2 Controllers - always register these as they are core to the controller
144168
&controller.ApisixGlobalRuleReconciler{
145169
Client: mgr.GetClient(),
146170
Scheme: mgr.GetScheme(),
@@ -185,13 +209,10 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
185209
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("ApisixUpstream"),
186210
Updater: updater,
187211
},
188-
&controller.GatewayProxyController{
189-
Client: mgr.GetClient(),
190-
Scheme: mgr.GetScheme(),
191-
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayProxy"),
192-
Provider: pro,
193-
},
194-
}, nil
212+
}...)
213+
214+
setupLog.Info("Controllers setup completed", "total_controllers", len(controllers))
215+
return controllers, nil
195216
}
196217

197218
func registerReadinessGVK(c client.Client, readier readiness.ReadinessManager) {

pkg/utils/cluster.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package utils
19+
20+
import (
21+
"github.com/go-logr/logr"
22+
"k8s.io/client-go/discovery"
23+
ctrl "sigs.k8s.io/controller-runtime"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
25+
26+
"github.com/apache/apisix-ingress-controller/internal/types"
27+
)
28+
29+
// HasAPIResource checks if a specific API resource is available in the current cluster.
30+
// It uses the Discovery API to query the cluster's available resources and returns true
31+
// if the resource is found, false otherwise.
32+
func HasAPIResource(mgr ctrl.Manager, obj client.Object) bool {
33+
return HasAPIResourceWithLogger(mgr, obj, ctrl.Log.WithName("api-detection"))
34+
}
35+
36+
// HasAPIResourceWithLogger is the same as HasAPIResource but accepts a custom logger
37+
// for more detailed debugging information.
38+
func HasAPIResourceWithLogger(mgr ctrl.Manager, obj client.Object, logger logr.Logger) bool {
39+
gvk := types.GvkOf(obj)
40+
groupVersion := gvk.GroupVersion().String()
41+
42+
logger = logger.WithValues(
43+
"kind", gvk.Kind,
44+
"group", gvk.Group,
45+
"version", gvk.Version,
46+
"groupVersion", groupVersion,
47+
)
48+
49+
// Create discovery client
50+
discoveryClient, err := discovery.NewDiscoveryClientForConfig(mgr.GetConfig())
51+
if err != nil {
52+
logger.Info("failed to create discovery client", "error", err)
53+
return false
54+
}
55+
56+
// Query server resources for the specific group/version
57+
apiResources, err := discoveryClient.ServerResourcesForGroupVersion(groupVersion)
58+
if err != nil {
59+
logger.Info("group/version not available in cluster", "error", err)
60+
return false
61+
}
62+
63+
// Check if the specific kind exists in the resource list
64+
for _, res := range apiResources.APIResources {
65+
if res.Kind == gvk.Kind {
66+
return true
67+
}
68+
}
69+
70+
logger.Info("API resource kind not found in group/version")
71+
return false
72+
}
73+
74+
func FormatGVK(obj client.Object) string {
75+
gvk := types.GvkOf(obj)
76+
return gvk.GroupVersion().String() + "." + gvk.Kind
77+
}

0 commit comments

Comments
 (0)