Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
czeslavo committed Mar 17, 2023
1 parent d96c76c commit 5675231
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 14 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ manifests.rbac: controller-gen
$(CONTROLLER_GEN) rbac:roleName=kong-ingress paths="./internal/controllers/configuration/"
$(CONTROLLER_GEN) rbac:roleName=kong-ingress-knative paths="./internal/controllers/knative/" output:rbac:artifacts:config=config/rbac/knative
$(CONTROLLER_GEN) rbac:roleName=kong-ingress-gateway paths="./internal/controllers/gateway/" output:rbac:artifacts:config=config/rbac/gateway
$(CONTROLLER_GEN) rbac:roleName=kong-ingress-crds paths="./internal/controllers/crds/" output:rbac:artifacts:config=config/rbac/crds

.PHONY: manifests.single
manifests.single: kustomize ## Compose single-file deployment manifests from building blocks
Expand Down
1 change: 1 addition & 0 deletions config/base/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ resources:
- ../rbac
- ../rbac/gateway
- ../rbac/knative
- ../rbac/crds
- ingressclass.yaml
- service.yaml
- serviceaccount.yaml
Expand Down
3 changes: 3 additions & 0 deletions config/rbac/crds/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resources:
- role.yaml
- role_binding.yaml
14 changes: 14 additions & 0 deletions config/rbac/crds/role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: kong-ingress-crds
rules:
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- list
- watch
12 changes: 12 additions & 0 deletions config/rbac/crds/role_binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kong-ingress-crds
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kong-ingress-crds
subjects:
- kind: ServiceAccount
name: kong-serviceaccount
namespace: kong
129 changes: 129 additions & 0 deletions internal/controllers/crds/optional_crds_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package crds

import (
"context"
"sync"
"time"

"github.com/go-logr/logr"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"

"github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/utils"
"github.com/kong/kubernetes-ingress-controller/v2/internal/util"
)

// +kubebuilder:rbac:groups="apiextensions.k8s.io",resources=customresourcedefinitions,verbs=list;watch

type Controller interface {
SetupWithManager(mgr ctrl.Manager) error
}

type OptionalCRDController struct {
Log logr.Logger
Manager ctrl.Manager
CacheSyncTimeout time.Duration
Controller Controller

neededGVRs []schema.GroupVersionResource

startControllerOnce sync.Once
}

func (r *OptionalCRDController) SetupWithManager(mgr ctrl.Manager) error {
if utils.CRDExists(mgr.GetClient().RESTMapper(), r.GVR) {
r.Log.Info("CRD exists, setting up its controller")
return r.Controller.SetupWithManager(mgr)
}

_, err := mgr.GetClient().RESTMapper().KindFor()
return !meta.IsNoMatchError(err)

r.Log.Info("CRD does not exist, setting up a watch for it")

c, err := controller.New("OptionalCRDs", mgr, controller.Options{
Reconciler: r,
LogConstructor: func(_ *reconcile.Request) logr.Logger {
return r.Log
},
CacheSyncTimeout: r.CacheSyncTimeout,
})
if err != nil {
return err
}

predicateFuncs := predicate.NewPredicateFuncs(r.isTheOptionalCRD)
predicateFuncs.DeleteFunc = func(e event.DeleteEvent) bool { return false }
predicateFuncs.GenericFunc = func(e event.GenericEvent) bool { return false }
predicateFuncs.UpdateFunc = func(e event.UpdateEvent) bool { return false }
return c.Watch(
&source.Kind{Type: &apiextensionsv1.CustomResourceDefinition{}},
&handler.EnqueueRequestForObject{},
)
}

func (r *OptionalCRDController) allNeededCRDsExist() bool {
for _, gvr := range r.neededGVRs {
if !utils.CRDExists(r.Manager.GetClient().RESTMapper(), gvr) {
return false
}
}

return true
}

func (r *OptionalCRDController) isTheOptionalCRD(obj client.Object) bool {
crd, ok := obj.(*apiextensionsv1.CustomResourceDefinition)
if !ok {
return false
}

cl := r.Manager.GetClient()
gvk, err := cl.RESTMapper().KindFor(r.GVR)
if err != nil {
r.Log.Error(err, "failed to get GVK for GVR", "gvr", r.GVR)
return false
}

if crd.Spec.Group == gvk.Group &&
crd.Spec.Versions[0].Name == gvk.Version &&
crd.Spec.Names.Kind == gvk.Kind {
return true
}
return false
}

func (r *OptionalCRDController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := r.Log.WithValues("CustomResourceDefinition", req.NamespacedName)

crd := new(apiextensionsv1.CustomResourceDefinition)
if err := r.Manager.GetClient().Get(ctx, req.NamespacedName, crd); err != nil {
if apierrors.IsNotFound(err) {
log.V(util.DebugLevel).Info("object enqueued no longer exists, skipping", "name", req.Name)
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
log.V(util.DebugLevel).Info("processing CRD", "name", req.Name)

var startControllerErr error
r.startControllerOnce.Do(func() {
log.Info("CRD created, setting up its controller")
startControllerErr = r.Controller.SetupWithManager(r.Manager)
})
if startControllerErr != nil {
return ctrl.Result{}, startControllerErr
}

return ctrl.Result{}, nil
}
32 changes: 18 additions & 14 deletions internal/manager/controllerdef.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

"github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/configuration"
"github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/crds"
"github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/gateway"
"github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/knative"
ctrlref "github.com/kong/kubernetes-ingress-controller/v2/internal/controllers/reference"
Expand Down Expand Up @@ -365,24 +366,27 @@ func setupControllers(
// Gateway API Controllers - Beta APIs
// ---------------------------------------------------------------------------
{
Enabled: featureGates[featuregates.GatewayFeature] && ShouldEnableCRDController(
schema.GroupVersionResource{
Enabled: featureGates[featuregates.GatewayFeature],
Controller: &crds.OptionalCRDController{
Manager: mgr,
Log: ctrl.Log.WithName("controllers").WithName(fmt.Sprintf("CRD/%s", featuregates.GatewayFeature)),
CacheSyncTimeout: c.CacheSyncTimeout,
GVR: schema.GroupVersionResource{
Group: gatewayv1beta1.GroupVersion.Group,
Version: gatewayv1beta1.GroupVersion.Version,
Resource: "gateways",
},
restMapper,
),
Controller: &gateway.GatewayReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName(featuregates.GatewayFeature),
Scheme: mgr.GetScheme(),
DataplaneClient: dataplaneClient,
PublishService: c.PublishService.OrEmpty().String(),
WatchNamespaces: c.WatchNamespaces,
EnableReferenceGrant: referenceGrantsEnabled,
CacheSyncTimeout: c.CacheSyncTimeout,
ReferenceIndexers: referenceIndexers,
Controller: &gateway.GatewayReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName(featuregates.GatewayFeature),
Scheme: mgr.GetScheme(),
DataplaneClient: dataplaneClient,
PublishService: c.PublishService.OrEmpty().String(),
WatchNamespaces: c.WatchNamespaces,
EnableReferenceGrant: referenceGrantsEnabled,
CacheSyncTimeout: c.CacheSyncTimeout,
ReferenceIndexers: referenceIndexers,
},
},
},
{
Expand Down
5 changes: 5 additions & 0 deletions internal/manager/scheme/scheme.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scheme

import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
knativev1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
Expand All @@ -18,6 +19,10 @@ import (
func Get(fg map[string]bool) (*runtime.Scheme, error) {
scheme := runtime.NewScheme()

if err := apiextensionsv1.AddToScheme(scheme); err != nil {
return nil, err
}

if err := clientgoscheme.AddToScheme(scheme); err != nil {
return nil, err
}
Expand Down

0 comments on commit 5675231

Please sign in to comment.