From 7da30d681ace39d013113fd587c5de55fc39971f Mon Sep 17 00:00:00 2001 From: b0m313 <13.spring.03@gmail.com> Date: Wed, 13 Dec 2023 21:34:58 +0000 Subject: [PATCH] feat(general): Add intent & intentbinding watcher --- .../controllers/general/general_controller.go | 86 +++++++++++++++++++ Nimbus/controllers/general/watch_binding.go | 58 +++++++++++++ Nimbus/controllers/general/watch_intent.go | 59 +++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 Nimbus/controllers/general/general_controller.go create mode 100644 Nimbus/controllers/general/watch_binding.go create mode 100644 Nimbus/controllers/general/watch_intent.go diff --git a/Nimbus/controllers/general/general_controller.go b/Nimbus/controllers/general/general_controller.go new file mode 100644 index 00000000..ca28a2d1 --- /dev/null +++ b/Nimbus/controllers/general/general_controller.go @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package general + +import ( + "context" + "fmt" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// GeneralController is a struct that holds a Kubernetes client and a WatcherIntent. +type GeneralController struct { + Client client.Client // Client is used to interact with the Kubernetes API. + WatcherIntent *WatcherIntent // WatcherIntent is a custom struct to manage specific operations. + WatcherBinding *WatcherBinding // WatcherBinding is a custom struct to manage SecurityIntentBinding operations. +} + +// NewGeneralController creates a new instance of GeneralController. +func NewGeneralController(client client.Client) (*GeneralController, error) { + if client == nil { + // If the client is not provided, return an error. + return nil, fmt.Errorf("GeneralController: Client is nil") + } + + // Create a new WatcherIntent. + watcherIntent, err := NewWatcherIntent(client) + if err != nil { + // If there is an error in creating WatcherIntent, return an error. + return nil, fmt.Errorf("GeneralController: Error creating WatcherIntent: %v", err) + } + + // Create a new WatcherBinding. + watcherBinding, err := NewWatcherBinding(client) + if err != nil { + // If there is an error in creating WatcherBinding, return an error. + return nil, fmt.Errorf("GeneralController: Error creating WatcherBinding: %v", err) + } + + // Return a new GeneralController instance with initialized fields. + return &GeneralController{ + Client: client, + WatcherIntent: watcherIntent, + WatcherBinding: watcherBinding, + }, nil +} + +func (gc *GeneralController) Reconcile(ctx context.Context, req ctrl.Request) (*BindingInfo, error) { + if gc == nil { + return nil, fmt.Errorf("GeneralController is nil") + } + + if gc.WatcherIntent == nil { + return nil, fmt.Errorf("WatcherIntent is nil") + } + + intent, err := gc.WatcherIntent.Reconcile(ctx, req) + if err != nil { + return nil, fmt.Errorf("Error in WatcherIntent.Reconcile: %v", err) + } + + if intent != nil { + return nil, nil + } + + if gc.WatcherBinding == nil { + return nil, fmt.Errorf("WatcherBinding is nil") + } + + binding, err := gc.WatcherBinding.Reconcile(ctx, req) + if err != nil { + return nil, fmt.Errorf("Error in WatcherBinding.Reconcile: %v", err) + } + + if binding != nil { + bindingInfo, err := MatchIntentAndBinding(ctx, gc.Client, binding) + if err != nil { + return nil, fmt.Errorf("Error in MatchIntentAndBinding: %v", err) + } + return bindingInfo, nil + } + + return nil, nil +} diff --git a/Nimbus/controllers/general/watch_binding.go b/Nimbus/controllers/general/watch_binding.go new file mode 100644 index 00000000..7e82a9e2 --- /dev/null +++ b/Nimbus/controllers/general/watch_binding.go @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package general + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + intentv1 "github.com/5GSEC/nimbus/Nimbus/api/v1" + "k8s.io/apimachinery/pkg/api/errors" +) + +// WatcherBinding is a struct that holds a Kubernetes client. +type WatcherBinding struct { + Client client.Client // Client to interact with Kubernetes resources. +} + +// NewWatcherBinding creates a new instance of WatcherBinding. +func NewWatcherBinding(client client.Client) (*WatcherBinding, error) { + if client == nil { + // Return an error if the client is not provided. + return nil, fmt.Errorf("WatcherBinding: Client is nil") + } + + // Return a new WatcherBinding instance with the provided client. + return &WatcherBinding{ + Client: client, + }, nil +} + +// Reconcile handles the reconciliation of the SecurityIntentBinding resources. +func (wb *WatcherBinding) Reconcile(ctx context.Context, req ctrl.Request) (*intentv1.SecurityIntentBinding, error) { + log := log.FromContext(ctx) + + if wb == nil || wb.Client == nil { + log.Info("WatcherBinding is nil or Client is nil in Reconcile") + return nil, fmt.Errorf("WatcherBinding or Client is not initialized") + } + + binding := &intentv1.SecurityIntentBinding{} + err := wb.Client.Get(ctx, types.NamespacedName{Name: req.Name, Namespace: req.Namespace}, binding) + + if err != nil { + if errors.IsNotFound(err) { + log.Info("SecurityIntentBinding resource not found. Ignoring since object must be deleted", "Name", req.Name, "Namespace", req.Namespace) + return nil, nil + } + log.Error(err, "Failed to get SecurityIntentBinding", "Name", req.Name, "Namespace", req.Namespace) + return nil, err + } + return binding, nil +} diff --git a/Nimbus/controllers/general/watch_intent.go b/Nimbus/controllers/general/watch_intent.go new file mode 100644 index 00000000..c5c302e9 --- /dev/null +++ b/Nimbus/controllers/general/watch_intent.go @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Authors of Nimbus + +package general + +import ( + "context" + "fmt" + + "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + intentv1 "github.com/5GSEC/nimbus/Nimbus/api/v1" + "k8s.io/apimachinery/pkg/api/errors" +) + +// WatcherIntent is a struct that holds a Kubernetes client. +type WatcherIntent struct { + Client client.Client // Client to interact with Kubernetes resources. +} + +// NewWatcherIntent creates a new instance of WatcherIntent. +func NewWatcherIntent(client client.Client) (*WatcherIntent, error) { + if client == nil { + // Return an error if the client is not provided. + return nil, fmt.Errorf("WatcherIntent: Client is nil") + } + + // Return a new WatcherIntent instance with the provided client. + return &WatcherIntent{ + Client: client, + }, nil +} + +// Reconcile is the method that handles the reconciliation of the Kubernetes resources. +func (wi *WatcherIntent) Reconcile(ctx context.Context, req ctrl.Request) (*intentv1.SecurityIntent, error) { + log := log.FromContext(ctx) + + if wi == nil || wi.Client == nil { + log.Info("WatcherIntent is nil or Client is nil in Reconcile") + return nil, fmt.Errorf("WatcherIntent or Client is not initialized") + } + + intent := &intentv1.SecurityIntent{} + err := wi.Client.Get(ctx, types.NamespacedName{Name: req.Name, Namespace: req.Namespace}, intent) + + if err == nil { + return intent, nil + } else { + if errors.IsNotFound(err) { + log.Info("SecurityIntent resource not found. Ignoring since object must be deleted", "Name", req.Name, "Namespace", req.Namespace) + return nil, nil + } + log.Error(err, "Failed to get SecurityIntent", "Name", req.Name, "Namespace", req.Namespace) + return nil, err + } +}