Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/apisix-conformance-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
ARCH: amd64
ENABLE_PROXY: "false"
BASE_IMAGE_TAG: "debug"
ADC_VERSION: "dev"
# ADC_VERSION: "dev"
run: |
echo "building images..."
make build-image
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/apisix-e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
ARCH: amd64
ENABLE_PROXY: "false"
BASE_IMAGE_TAG: "debug"
ADC_VERSION: "dev"
# ADC_VERSION: "dev"
run: |
echo "building images..."
make build-image
Expand Down
51 changes: 36 additions & 15 deletions internal/manager/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/apache/apisix-ingress-controller/internal/manager/readiness"
"github.com/apache/apisix-ingress-controller/internal/provider"
types "github.com/apache/apisix-ingress-controller/internal/types"
"github.com/apache/apisix-ingress-controller/pkg/utils"
)

// K8s
Expand Down Expand Up @@ -97,40 +98,55 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
if err := indexer.SetupIndexer(mgr); err != nil {
return nil, err
}
return []Controller{
&controller.GatewayClassReconciler{

setupLog := ctrl.LoggerFrom(ctx).WithName("setup")
var controllers []Controller

// Gateway API Controllers - conditional registration based on API availability
for resource, controller := range map[client.Object]Controller{
&gatewayv1.GatewayClass{}: &controller.GatewayClassReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayClass"),
Updater: updater,
},
&controller.GatewayReconciler{
&gatewayv1.Gateway{}: &controller.GatewayReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Gateway"),
Provider: pro,
Updater: updater,
},
&controller.HTTPRouteReconciler{
&gatewayv1.HTTPRoute{}: &controller.HTTPRouteReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("HTTPRoute"),
Provider: pro,
Updater: updater,
Readier: readier,
},
&controller.IngressReconciler{
&v1alpha1.Consumer{}: &controller.ConsumerReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Ingress"),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Consumer"),
Provider: pro,
Updater: updater,
Readier: readier,
},
&controller.ConsumerReconciler{
} {
if utils.HasAPIResource(mgr, resource) {
controllers = append(controllers, controller)
} else {
setupLog.Info("Skipping controller setup, API not found in cluster", "api", utils.FormatGVK(resource))
}
}

controllers = append(controllers, []Controller{
// Core Kubernetes Controllers - always register these
&controller.IngressReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Consumer"),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("Ingress"),
Provider: pro,
Updater: updater,
Readier: readier,
Expand All @@ -141,6 +157,14 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("IngressClass"),
Provider: pro,
},
// Gateway Proxy Controller - always register this as it is core to the controller
&controller.GatewayProxyController{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayProxy"),
Provider: pro,
},
// APISIX v2 Controllers - always register these as they are core to the controller
&controller.ApisixGlobalRuleReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand Down Expand Up @@ -185,13 +209,10 @@ func setupControllers(ctx context.Context, mgr manager.Manager, pro provider.Pro
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("ApisixUpstream"),
Updater: updater,
},
&controller.GatewayProxyController{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.LoggerFrom(ctx).WithName("controllers").WithName("GatewayProxy"),
Provider: pro,
},
}, nil
}...)

setupLog.Info("Controllers setup completed", "total_controllers", len(controllers))
return controllers, nil
}

func registerReadinessGVK(c client.Client, readier readiness.ReadinessManager) {
Expand Down
77 changes: 77 additions & 0 deletions pkg/utils/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package utils

import (
"github.com/go-logr/logr"
"k8s.io/client-go/discovery"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/apache/apisix-ingress-controller/internal/types"
)

// HasAPIResource checks if a specific API resource is available in the current cluster.
// It uses the Discovery API to query the cluster's available resources and returns true
// if the resource is found, false otherwise.
func HasAPIResource(mgr ctrl.Manager, obj client.Object) bool {
return HasAPIResourceWithLogger(mgr, obj, ctrl.Log.WithName("api-detection"))
}

// HasAPIResourceWithLogger is the same as HasAPIResource but accepts a custom logger
// for more detailed debugging information.
func HasAPIResourceWithLogger(mgr ctrl.Manager, obj client.Object, logger logr.Logger) bool {
gvk := types.GvkOf(obj)
groupVersion := gvk.GroupVersion().String()

logger = logger.WithValues(
"kind", gvk.Kind,
"group", gvk.Group,
"version", gvk.Version,
"groupVersion", groupVersion,
)

// Create discovery client
discoveryClient, err := discovery.NewDiscoveryClientForConfig(mgr.GetConfig())
if err != nil {
logger.Info("failed to create discovery client", "error", err)
return false
}

// Query server resources for the specific group/version
apiResources, err := discoveryClient.ServerResourcesForGroupVersion(groupVersion)
if err != nil {
logger.Info("group/version not available in cluster", "error", err)
return false
}

// Check if the specific kind exists in the resource list
for _, res := range apiResources.APIResources {
if res.Kind == gvk.Kind {
return true
}
}

logger.Info("API resource kind not found in group/version")
return false
}

func FormatGVK(obj client.Object) string {
gvk := types.GvkOf(obj)
return gvk.GroupVersion().String() + "." + gvk.Kind
}
Loading