Index: /branches/main/array-ingress-controller/controller/consts.go
===================================================================
--- /branches/main/array-ingress-controller/controller/consts.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/consts.go	(working copy)
@@ -0,0 +1,5 @@
+package controller
+
+const(
+	LeaderElectionID = "array-ingress-controller-leader"
+)
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/ha_leader_elect.go
===================================================================
--- /branches/main/array-ingress-controller/controller/ha_leader_elect.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/ha_leader_elect.go	(working copy)
@@ -0,0 +1,52 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package controller
+
+import (
+	"context"
+	"os"
+	"time"
+
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/manager"
+	"arraynetworks.com/array-ingress-controller/logger"
+)
+
+var (
+	LeaseDuration = 15 * time.Second
+	RenewDeadline = 10 * time.Second
+	RetryPeriod   = 5 * time.Second
+)
+
+func StartLeaderElection(ctx context.Context, leaderFunc func(context.Context)) {
+	logger.Info("Initializing Kubernetes Leader Election...")
+
+	namespace, exists := os.LookupEnv("CONTROLLER_NAMESPACE")
+	if !exists || namespace == "" {
+		logger.Fatalf("LEASE_NAMESPACE environment variable not set. Exiting...")
+	}
+
+	mgr, err := manager.New(ctrl.GetConfigOrDie(), manager.Options{
+		LeaderElection:          true,
+		LeaderElectionID:        LeaderElectionID,
+		LeaderElectionNamespace: namespace,
+		LeaseDuration:           &LeaseDuration,
+		RenewDeadline:           &RenewDeadline,
+		RetryPeriod:             &RetryPeriod,
+	})
+	if err != nil {
+		logger.Fatalf("Failed to create manager: %v", err)
+	}
+
+	go func() {
+		<-mgr.Elected()
+		logger.Info("This pod has been elected as the leader.")
+		leaderFunc(ctx)
+	}()
+
+	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
+		logger.Fatalf("Manager failed: %v", err)
+	}
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/admission/main.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/admission/main.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/admission/main.go	(working copy)
@@ -0,0 +1,83 @@
+package controller
+
+import (
+	"fmt"
+	"net/http"
+
+	admissionv1 "k8s.io/api/admission/v1"
+	networking "k8s.io/api/networking/v1"
+	apiequality "k8s.io/apimachinery/pkg/api/equality"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/serializer/json"
+	"k8s.io/klog/v2"
+)
+
+var ingressResource = metav1.GroupVersionKind{
+	Group:   networking.GroupName,
+	Version: "v1",
+	Kind:    "Ingress",
+}
+
+// HandleAdmission populates the admission Response
+// with Allowed=false if the Object is an ingress that would prevent nginx to reload the configuration
+// with Allowed=true otherwise
+func (ia *IngressAdmission) HandleAdmission(obj runtime.Object) (runtime.Object, error) {
+	review, isV1 := obj.(*admissionv1.AdmissionReview)
+	if !isV1 {
+		return nil, fmt.Errorf("request is not of type AdmissionReview v1 or v1beta1")
+	}
+
+	if !apiequality.Semantic.DeepEqual(review.Request.Kind, ingressResource) {
+		return nil, fmt.Errorf("rejecting admission review because the request does not contain an Ingress resource but %s with name %s in namespace %s",
+			review.Request.Kind.String(), review.Request.Name, review.Request.Namespace)
+	}
+
+	status := &admissionv1.AdmissionResponse{}
+	status.UID = review.Request.UID
+
+	ingress := networking.Ingress{}
+
+	codec := json.NewSerializerWithOptions(json.DefaultMetaFactory, scheme, scheme, json.SerializerOptions{
+		Pretty: true,
+	})
+	_, _, err := codec.Decode(review.Request.Object.Raw, nil, &ingress)
+	if err != nil {
+		klog.ErrorS(err, "failed to decode ingress")
+		status.Allowed = false
+		status.Result = &metav1.Status{
+			Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
+			Message: err.Error(),
+		}
+
+		review.Response = status
+		return review, nil
+	}
+
+	// Adds the warnings regardless of operation being allowed or not
+	warning, err := ia.Checker.CheckWarning(&ingress)
+	if err != nil {
+		klog.ErrorS(err, "failed to get ingress warnings")
+	}
+	if len(warning) > 0 {
+		status.Warnings = warning
+	}
+
+	if err := ia.Checker.CheckIngress(&ingress); err != nil {
+		klog.ErrorS(err, "invalid ingress configuration", "ingress", fmt.Sprintf("%v/%v", review.Request.Namespace, review.Request.Name))
+		status.Allowed = false
+		status.Result = &metav1.Status{
+			Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
+			Message: err.Error(),
+		}
+
+		review.Response = status
+		return review, nil
+	}
+
+	klog.InfoS("successfully validated configuration, accepting", "ingress", fmt.Sprintf("%v/%v", review.Request.Namespace, review.Request.Name))
+	status.Allowed = true
+	review.Response = status
+
+	return review, nil
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/admission/server.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/admission/server.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/admission/server.go	(working copy)
@@ -0,0 +1,76 @@
+package controller
+
+import (
+	"io"
+	"net/http"
+
+	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/serializer/json"
+	"k8s.io/klog/v2"
+)
+
+var scheme = runtime.NewScheme()
+
+func init() {
+	if err := admissionv1.AddToScheme(scheme); err != nil {
+		klog.ErrorS(err, "Failed to add scheme")
+	}
+}
+
+// AdmissionController checks if an object
+// is allowed in the cluster
+type AdmissionController interface {
+	HandleAdmission(runtime.Object) (runtime.Object, error)
+}
+
+// AdmissionControllerServer implements an HTTP server
+// for kubernetes validating webhook
+// https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook
+type AdmissionControllerServer struct {
+	AdmissionController AdmissionController
+}
+
+// NewAdmissionControllerServer instantiates an admission controller server with
+// a default codec
+func NewAdmissionControllerServer(ac AdmissionController) *AdmissionControllerServer {
+	return &AdmissionControllerServer{
+		AdmissionController: ac,
+	}
+}
+
+// ServeHTTP implements http.Server method
+func (acs *AdmissionControllerServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	defer req.Body.Close()
+
+	data, err := io.ReadAll(req.Body)
+	if err != nil {
+		klog.ErrorS(err, "Failed to read request body")
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	codec := json.NewSerializerWithOptions(json.DefaultMetaFactory, scheme, scheme, json.SerializerOptions{
+		Pretty: true,
+	})
+
+	obj, _, err := codec.Decode(data, nil, nil)
+	if err != nil {
+		klog.ErrorS(err, "Failed to decode request body")
+		w.WriteHeader(http.StatusBadRequest)
+		return
+	}
+
+	result, err := acs.AdmissionController.HandleAdmission(obj)
+	if err != nil {
+		klog.ErrorS(err, "failed to process webhook request")
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	if err := codec.Encode(result, w); err != nil {
+		klog.ErrorS(err, "failed to encode response body")
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/admission/validate.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/admission/validate.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/admission/validate.go	(working copy)
@@ -0,0 +1,73 @@
+package controller
+
+import (
+	"fmt"
+	"strings"
+	"annotations"
+	"health"
+
+	networking "k8s.io/api/networking/v1"
+	"k8s.io/klog/v2"
+)
+
+// Checker must return an error if the ingress provided as argument
+// contains invalid instructions
+type Checker interface {
+	CheckIngress(ing *networking.Ingress) error
+}
+
+// IngressAdmission implements the AdmissionController interface
+// to handle Admission Reviews and deny requests that are not validated
+type IngressAdmission struct {
+	Checker   Checker
+	Namespace string
+}
+
+// CheckIngress returns an error in case the provided ingress, when added
+// to the current configuration, generates an invalid configuration
+func (n *IngressAdmission) CheckIngress(ing *networking.Ingress) error {
+
+	if ing == nil {
+		// no ingress to add, no state change
+		return nil
+	}
+
+	// Skip checks if the ingress is marked as deleted
+	if !ing.DeletionTimestamp.IsZero() {
+		return nil
+	}
+
+	/*
+		// Do not attempt to validate an ingress that's not meant to be controlled by the current instance of the controller.
+		if ingressClass, err := GetIngressClass(ing); ingressClass == "array" {
+			klog.Warningf("ignoring ingress %v in %v based on annotation %v: %v", ing.Name, ing.ObjectMeta.Namespace, ingressClass, err)
+			return nil
+		}
+
+		if n.Namespace != "" && ing.ObjectMeta.Namespace != n.cfg.Namespace {
+			fmt.Println("ignoring ingress %v in namespace %v different from the namespace watched %s", ing.Name, ing.ObjectMeta.Namespace, n.Namespace)
+			return nil
+		}
+	*/
+
+	annots := annotations.Extract(ing)
+
+	for key, annotationData := range annots {
+		var hlth_annots &health.HealthAnnotation
+		// Unmarshal the JSON data into the struct
+		if err := json.Unmarshal([]byte(annotationData), &hlth_annots); err != nil {
+			return errors.New("invalid JSON format")
+		}
+
+		parserInstance := hlth_annots.NewParser()
+		// Iterate over the Validators and call each function
+		for key, validator := range parserInstance.annotationConfig.Validators {
+			if err := validator(); err != nil {
+				fmt.Printf("Validation error for %s: %s\n", key, err)
+			} else {
+				fmt.Printf("Validation passed for %s\n", key)
+			}
+		}
+	}
+	return nil
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/controller.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/controller.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/controller.go	(working copy)
@@ -0,0 +1,150 @@
+package controller
+
+import (
+	"fmt"
+	"time"
+
+	v1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/util/runtime"
+	"k8s.io/client-go/informers"
+	clientset "k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/tools/cache"
+)
+
+// EventType type of event associated with an informer
+type EventType string
+
+const (
+	// CreateEvent event associated with new objects in an informer
+	CreateEvent EventType = "CREATE"
+	// UpdateEvent event associated with an object update in an informer
+	UpdateEvent EventType = "UPDATE"
+	// DeleteEvent event associated when an object is removed from an informer
+	DeleteEvent EventType = "DELETE"
+	// ConfigurationEvent event associated when a controller configuration object is created or updated
+	ConfigurationEvent EventType = "CONFIGURATION"
+)
+
+// Event holds the context of an event.
+type Event struct {
+	Type EventType
+	Obj  interface{}
+}
+
+// Informer defines the required SharedIndexInformers that interact with the API server.
+type Informer struct {
+	Ingress cache.SharedIndexInformer
+	Pod     cache.SharedIndexInformer
+	Service cache.SharedIndexInformer
+}
+
+// Run initiates the synchronization of the informers against the API server.
+func (i *Informer) Run(stopCh chan struct{}) {
+	go i.Pod.Run(stopCh)
+	go i.Service.Run(stopCh)
+
+	// wait for all involved caches to be synced before processing items
+	// from the queue
+	if !cache.WaitForCacheSync(stopCh,
+		i.Service.HasSynced,
+		i.Pod.HasSynced,
+	) {
+		runtime.HandleError(fmt.Errorf("timed out waiting for caches to sync"))
+	}
+
+	// in big clusters, deltas can keep arriving even after HasSynced
+	// functions have returned 'true'
+	time.Sleep(1 * time.Second)
+
+	// we can start syncing ingress objects only after other caches are
+	// ready, because ingress rules require content from other listers, and
+	// 'add' events get triggered in the handlers during caches population.
+	go i.Ingress.Run(stopCh)
+	if !cache.WaitForCacheSync(stopCh,
+		i.Ingress.HasSynced,
+	) {
+		runtime.HandleError(fmt.Errorf("timed out waiting for caches to sync"))
+	}
+}
+
+func New(
+	namespace string,
+	namespaceSelector labels.Selector,
+	resyncPeriod time.Duration,
+	client clientset.Interface,
+) {
+
+	// create informers factory, enable and assign required informers
+	infFactory := informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod,
+		informers.WithNamespace(namespace),
+	)
+
+	// Create the SharedInformerFactory and Pod Informer
+	podsInformer := infFactory.Core().V1().Pods().Informer()
+
+	// Create the SharedInformerFactory and Ingress Informer
+	ingressInformer := infFactory.Networking().V1().Ingresses().Informer()
+
+	// Create the SharedInformerFactory and Service Informer
+	servicesInformer := infFactory.Core().V1().Services().Informer()
+
+	// Define an event handler for Pod events
+	podsInformer.AddEventHandler(
+		cache.ResourceEventHandlerFuncs{
+			AddFunc: func(obj interface{}) {
+				pod := obj.(*v1.Pod)
+				fmt.Printf("Pod added: %s\n", pod.Name)
+			},
+			UpdateFunc: func(oldObj, newObj interface{}) {
+				oldPod := oldObj.(*v1.Pod)
+				newPod := newObj.(*v1.Pod)
+				fmt.Printf("Pod updated: %s -> %s\n", oldPod.Name, newPod.Name)
+			},
+			DeleteFunc: func(obj interface{}) {
+				pod := obj.(*v1.Pod)
+				fmt.Printf("Pod deleted: %s\n", pod.Name)
+			},
+		},
+	)
+
+	// Define an event handler for Ingress events
+	ingressInformer.AddEventHandler(
+		cache.ResourceEventHandlerFuncs{
+			AddFunc: func(obj interface{}) {
+				ingress := obj.(*networkingv1.Ingress)
+				fmt.Printf("Ingress added: %s\n", ingress.Name)
+			},
+			UpdateFunc: func(oldObj, newObj interface{}) {
+				oldIngress := oldObj.(*networkingv1.Ingress)
+				newIngress := newObj.(*networkingv1.Ingress)
+				fmt.Printf("Ingress updated: %s -> %s\n", oldIngress.Name, newIngress.Name)
+			},
+			DeleteFunc: func(obj interface{}) {
+				ingress := obj.(*networkingv1.Ingress)
+				fmt.Printf("Ingress deleted: %s\n", ingress.Name)
+			},
+		},
+	)
+
+	// Define an event handler for Service events
+	servicesInformer.AddEventHandler(
+		cache.ResourceEventHandlerFuncs{
+			AddFunc: func(obj interface{}) {
+				service := obj.(*v1.Service)
+				fmt.Printf("Service added: %s\n", service.Name)
+			},
+			UpdateFunc: func(oldObj, newObj interface{}) {
+				oldService := oldObj.(*v1.Service)
+				newService := newObj.(*v1.Service)
+				fmt.Printf("Service updated: %s -> %s\n", oldService.Name, newService.Name)
+			},
+			DeleteFunc: func(obj interface{}) {
+				service := obj.(*v1.Service)
+				fmt.Printf("Service deleted: %s\n", service.Name)
+			},
+		},
+	)
+
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/annotations.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/annotations.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/annotations.go	(working copy)
@@ -0,0 +1,45 @@
+package annotations
+
+import (
+    "encoding/json"
+    "fmt"
+    "strings"
+    "reflect"
+)
+
+type Annotations struct {
+    Key   string
+    Value interface{}
+}
+
+// Extract extracts the annotations from an Ingress
+func Extract(ing *networking.Ingress) ([]Annotations, error) {
+	var annotations []Annotation
+    if ingress.Annotations != nil {
+        for key, value := range ingress.Annotations {
+            // Check if the annotation key starts with "virtual-server.arraynetworks"
+            if strings.HasPrefix(key, "virtual-server.arraynetworks") {
+                // Attempt to parse the value as JSON
+                var jsonValue interface{}
+                if err := json.Unmarshal([]byte(value), &jsonValue); err == nil {
+                    annotations = append(annotations, Annotation{Key: key, Value: jsonValue})
+                } else {
+                    // If not JSON, treat as a string or other literal
+                    annotations = append(annotations, Annotation{Key: key, Value: value})
+                }
+            }
+        }
+    }
+    return annotations, nil
+}
+
+func ExtractAnnotationValueType(value interface{}) string {
+    // Use reflection to get the type of the value
+    valueType := reflect.TypeOf(value)
+    // Check if the valueType is nil, which means the value is nil
+    if valueType == nil {
+        return "nil"
+    }
+    // Return the kind of the type as a string
+    return valueType.Kind().String()
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/health/main.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/health/main.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/health/main.go	(working copy)
@@ -0,0 +1,72 @@
+package healthcheck
+
+import (
+	"parser"
+	networking "k8s.io/api/networking/v1"
+)
+
+var validProtocols = []string{"auto_http", "http", "https", "grpc", "grpcs", "fcgi"}
+
+const (
+	http             = "HTTP"
+	healthAnnotation = "health"
+)
+
+// Health Annotation representation
+//apv.arraynetworks.com/health
+//{ "protocol": "string", "interval": int, "timeout": int, "retries": int }
+
+// HealthAnnotation represents the expected structure of the health annotation
+type HealthAnnotation struct {
+    Protocol string `json:"protocol"`
+    Interval int    `json:"interval"`
+    Timeout  int    `json:"timeout"`
+    Retries  int    `json:"retries"`
+}
+
+// Assuming parser.AnnotationConfig supports a slice of validators
+/*
+var healthConfig = parser.AnnotationConfig{
+    Validators: map[string]parser.AnnotationValidator{
+		"protocol": parser.ValidateOptions(validProtocols, false, true),
+		"interval": parser.ValidateOptions(validProtocols, false, true),
+		"timeout": parser.ValidateOptions(validProtocols, false, true),
+		"retries": parser.ValidateOptions(validProtocols, false, true),
+	}
+}
+*/
+
+
+type health struct {
+	annotationConfig parser.AnnotationConfig
+}
+
+// NewParser creates a new backend protocol annotation parser
+func (ha *HealthAnnotation) NewParser() *health{
+	return &health{
+		annotationConfig: parser.AnnotationConfig{
+			Validators: map[string]parser.AnnotationValidator{
+				"protocol": parser.ValidateOptions(ha.Protocol, validProtocols, false, true),
+				"interval": parser.ValidateInt(ha.Interval),
+				"timeout": parser.ValidateInt(ha.Timeout),
+				"retries": parser.ValidateInt(ha.Retries),
+			}
+		}
+	}
+}
+
+// ParseAnnotations parses the annotations contained in the ingress
+// rule used to indicate the health check.
+func (h health) Parse(ing *networking.Ingress) (interface{}, error) {
+	if ing.GetAnnotations() == nil {
+		return nil, nil
+	}
+	annots, err := parser.GetStringAnnotation(healthAnnotation, ing, h.annotationConfig.Annotations)
+	if err != nil {
+		if errors.IsValidationError(err) {
+			klog.Warningf("validation error %s. Using HTTP as protocol", err)
+		}
+		return nil, err
+	}
+	return annots, nil
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/main.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/main.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/main.go	(working copy)
@@ -0,0 +1,126 @@
+package parser
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+
+	networking "k8s.io/api/networking/v1"
+)
+
+// DefaultAnnotationsPrefix defines the common prefix used in the nginx ingress controller
+const (
+	DefaultAnnotationsPrefix  = "apv.arraynetworks.com"
+)
+
+// AnnotationConfig defines the configuration that a single annotation field
+// has, with the Validator and the documentation of this field.
+type AnnotationConfig struct {
+	// Validator defines a function to validate the annotation value
+	Validators map[string]AnnotationValidator
+}
+
+type ingAnnotations map[string]string
+
+func (a ingAnnotations) parseBool(name string) (bool, error) {
+	val, ok := a[name]
+	if ok {
+		b, err := strconv.ParseBool(val)
+		if err != nil {
+			return false, errors.NewInvalidAnnotationContent(name, val)
+		}
+		return b, nil
+	}
+	return false, errors.ErrMissingAnnotations
+}
+
+func (a ingAnnotations) parseString(name string) (string, error) {
+	val, ok := a[name]
+	if ok {
+		s := normalizeString(val)
+		if s == "" {
+			return "", errors.NewInvalidAnnotationContent(name, val)
+		}
+
+		return s, nil
+	}
+	return "", errors.ErrMissingAnnotations
+}
+
+func (a ingAnnotations) parseInt(name string) (int, error) {
+	val, ok := a[name]
+	if ok {
+		i, err := strconv.Atoi(val)
+		if err != nil {
+			return 0, errors.NewInvalidAnnotationContent(name, val)
+		}
+		return i, nil
+	}
+	return 0, errors.ErrMissingAnnotations
+}
+
+func (a ingAnnotations) parseFloat32(name string) (float32, error) {
+	val, ok := a[name]
+	if ok {
+		i, err := strconv.ParseFloat(val, 32)
+		if err != nil {
+			return 0, errors.NewInvalidAnnotationContent(name, val)
+		}
+		return float32(i), nil
+	}
+	return 0, errors.ErrMissingAnnotations
+}
+
+// GetBoolAnnotation extracts a boolean from an Ingress annotation
+func GetBoolAnnotation(name string, ing *networking.Ingress, fields AnnotationFields) (bool, error) {
+	v, err := checkAnnotation(name, ing, fields)
+	if err != nil {
+		return false, err
+	}
+	return ingAnnotations(ing.GetAnnotations()).parseBool(v)
+}
+
+// GetStringAnnotation extracts a string from an Ingress annotation
+func GetStringAnnotation(name string, ing *networking.Ingress, fields AnnotationFields) (string, error) {
+	v, err := checkAnnotation(name, ing, fields)
+	if err != nil {
+		return "", err
+	}
+
+	return ingAnnotations(ing.GetAnnotations()).parseString(v)
+}
+
+// GetIntAnnotation extracts an int from an Ingress annotation
+func GetIntAnnotation(name string, ing *networking.Ingress, fields AnnotationFields) (int, error) {
+	v, err := checkAnnotation(name, ing, fields)
+	if err != nil {
+		return 0, err
+	}
+	return ingAnnotations(ing.GetAnnotations()).parseInt(v)
+}
+
+// GetFloatAnnotation extracts a float32 from an Ingress annotation
+func GetFloatAnnotation(name string, ing *networking.Ingress, fields AnnotationFields) (float32, error) {
+	v, err := checkAnnotation(name, ing, fields)
+	if err != nil {
+		return 0, err
+	}
+	return ingAnnotations(ing.GetAnnotations()).parseFloat32(v)
+}
+
+// GetAnnotationWithPrefix returns the prefix of ingress annotations
+func GetAnnotationWithPrefix(suffix string) string {
+	return fmt.Sprintf("%v/%v", DefaultAnnotationsPrefix, suffix)
+}
+
+func TrimAnnotationPrefix(annotation string) string {
+	return strings.TrimPrefix(annotation, DefaultAnnotationsPrefix+"/")
+}
+
+func normalizeString(input string) string {
+	trimmedContent := []string{}
+	for _, line := range strings.Split(input, "\n") {
+		trimmedContent = append(trimmedContent, strings.TrimSpace(line))
+	}
+	return strings.Join(trimmedContent, "\n")
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/validator.go
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/validator.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/parser/validator.go	(working copy)
@@ -0,0 +1,107 @@
+package parser
+
+import (
+	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+
+	machineryvalidation "k8s.io/apimachinery/pkg/api/validation"
+)
+
+type AnnotationValidator func(string) error
+
+var (
+	alphaNumericChars    = `\-\.\_\~a-zA-Z0-9\/:`
+	extendedAlphaNumeric = alphaNumericChars + ", "
+	regexEnabledChars    = regexp.QuoteMeta(`^$[](){}*+?|&=\`)
+	urlEnabledChars      = regexp.QuoteMeta(`,:?&=`)
+	// MaliciousRegex defines chars that are known to inject RCE
+	MaliciousRegex = regexp.MustCompile(`\r|\n`)
+	// IsValidRegex checks if the tested string can be used as a regex, but without any weird character.
+	// It includes regex characters for paths that may contain regexes
+	//
+	IsValidRegex = regexp.MustCompile("^[/" + alphaNumericChars + regexEnabledChars + "]*$")
+)
+
+// ValidateArrayOfServerName validates if all fields on a Server name annotation are
+// regexes. They can be *.something*, ~^www\d+\.example\.com$ but not fancy character
+func ValidateArrayOfServerName(value string) error {
+	for _, fqdn := range strings.Split(value, ",") {
+		if err := ValidateServerName(fqdn); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// ValidateServerName validates if the passed value is an acceptable server name. The server name
+// can contain regex characters, as those are accepted values on nginx configuration
+func ValidateServerName(value string) error {
+	value = strings.TrimSpace(value)
+	if !IsValidRegex.MatchString(value) {
+		return fmt.Errorf("value %s is invalid server name", value)
+	}
+	return nil
+}
+
+// ValidateRegex receives a regex as an argument and uses it to validate
+// the value of the field.
+// Annotation can define if the spaces should be trimmed before validating the value
+func ValidateRegex(s string, regex *regexp.Regexp, removeSpace bool) error {
+	if removeSpace {
+		s = strings.ReplaceAll(s, " ", "")
+	}
+	if !regex.MatchString(s) {
+		return fmt.Errorf("value %s is invalid", s)
+	}
+	if MaliciousRegex.MatchString(s) {
+		return fmt.Errorf("value %s contains malicious string", s)
+	}
+
+	return nil
+}
+
+// ValidateOptions receives an array of valid options that can be the value of annotation.
+// If no valid option is found, it will return an error
+func ValidateOptions(s string, options []string, caseSensitive, trimSpace bool) error {
+	if trimSpace {
+		s = strings.TrimSpace(s)
+	}
+	if !caseSensitive {
+		s = strings.ToLower(s)
+	}
+	for _, option := range options {
+		if s == option {
+			return nil
+		}
+	}
+	return fmt.Errorf("value does not match any valid option")
+}
+
+// ValidateBool validates if the specified value is a bool
+func ValidateBool(value string) error {
+	_, err := strconv.ParseBool(value)
+	return err
+}
+
+// ValidateInt validates if the specified value is an integer
+func ValidateInt(value string) error {
+	_, err := strconv.Atoi(value)
+	return err
+}
+
+// ValidateCIDRs validates if the specified value is an array of IPs and CIDRs
+func ValidateCIDRs(value string) error {
+	_, err := net.ParseCIDRs(value)
+	return err
+}
+
+// ValidateServiceName validates if a provided service name is a valid string
+func ValidateServiceName(value string) error {
+	errs := machineryvalidation.NameIsDNS1035Label(value, false)
+	if len(errs) != 0 {
+		return fmt.Errorf("annotation does not contain a valid service name: %+v", errs)
+	}
+	return nil
+}
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/whitelisting/main.go	(added)
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/whitelisting/main.go	(revision 0)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/annotation/whitelisting/main.go	(revision 0)
Index: /branches/main/array-ingress-controller/controller/k8s-controller/ingress/validator/validator.go	(added)
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/ingress/validator/validator.go	(revision 0)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/ingress/validator/validator.go	(revision 0)
Index: /branches/main/array-ingress-controller/controller/k8s-controller/main.go	(added)
===================================================================
--- /branches/main/array-ingress-controller/controller/k8s-controller/main.go	(revision 0)
+++ /branches/main/array-ingress-controller/controller/k8s-controller/main.go	(revision 0)
Index: /branches/main/array-ingress-controller/controller/openshift-controller/cmd.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/cmd.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/cmd.go	(working copy)
@@ -1,53 +1,56 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
  
 package openshift
 
 import (
-    "fmt"
-    "os"
-    "os/signal"
-    "syscall"
-    "time"
-
-    "my-k8s-informers/pkg/informers"
-    "my-k8s-informers/pkg/utils"
-
-    "k8s.io/client-go/informers"
-    "k8s.io/client-go/kubernetes"
-     routev1 "github.com/openshift/client-go/route/clientset/versioned"
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+
+    arrayinformers "arraynetworks.com/array-ingress-controller/controller/openshift-controller/informers"
+    "arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	"arraynetworks.com/array-ingress-controller/logger"
+    //routev1 "github.com/openshift/client-go/route/clientset/versioned"
+	"k8s.io/client-go/informers"
+	//"k8s.io/client-go/kubernetes"
 )
 
-type ControllerConfig struct {
-	client *kubernetes.Clientset
-	reconcilePeriod time.Duration
+var(
+    log	        logger.Logger
+)
+
+func init(){
+	log	= logger.GetLogger()
 }
 
 func  StartControllers() {
     // Create Kubernetes client
     kubeClient, err := utils.CreateKubeClient()
     if err != nil {
-        fmt.Fprintf(os.Stderr, "Error creating Kubernetes client: %v\n", err)
+        log.Errorf("Error creating Kubernetes client: %v\n", err)
         os.Exit(1)
     }
 
 	// Create OpenShift Route client
     routeClient, err := utils.CreateRouteClient()
     if err != nil {
-        fmt.Fprintf(os.Stderr, "Error creating OpenShift route client: %v\n", err)
+        log.Errorf("Error creating OpenShift route client: %v\n", err)
         os.Exit(1)
     }
 
     // Create shared informer factory
-    factory := informers.NewSharedInformerFactory(kubeClient, reconcilePeriod)
-
+    factory := informers.NewSharedInformerFactory(kubeClient, 1*time.Minute)
+    
     // Create a channel to stop the informers
     stopCh := make(chan struct{})
 
     // Start Pod informer
-    informers.StartPodInformer(factory, stopCh)
-    informers.StartRouteInformer(routeClient, stopCh)
+    go arrayinformers.StartRouteInformer(routeClient, stopCh)
+    go arrayinformers.StartEndpointInformer(factory, stopCh)
+    //informers.StartServiceInformer(factory, stopCh)
 
     // Handle shutdown signals
     sigCh := make(chan os.Signal, 1)
@@ -56,5 +59,5 @@
 
     // Stop informers
     close(stopCh)
-    fmt.Println("Shutting down informers...")
+    log.Info("Shutting down informers...")
 }
Index: /branches/main/array-ingress-controller/controller/openshift-controller/go.mod
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/go.mod	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/go.mod	(working copy)
@@ -2,12 +2,32 @@
 
 go 1.23.6
 
+replace (
+	arraynetworks.com/array-ingress-controller/configstore => ../../configstore
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers => ./handlers
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/informers => ./informers
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils => ./utils
+	arraynetworks.com/array-ingress-controller/logger => ../../logger
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv => ../../task-manager/openshift/apv
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf => ../../task-manager/openshift/asf
+	arraynetworks.com/array-ingress-controller/task-manager/task => ../../task-manager/task
+)
+
 require (
-	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/informers v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
 	k8s.io/client-go v0.32.2
 )
 
 require (
+	arraynetworks.com/array-ingress-controller/configstore v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/task-manager/task v0.0.0-00010101000000-000000000000 // indirect
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
@@ -15,31 +35,43 @@
 	github.com/go-openapi/jsonpointer v0.21.0 // indirect
 	github.com/go-openapi/jsonreference v0.20.2 // indirect
 	github.com/go-openapi/swag v0.23.0 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/google/gnostic-models v0.6.8 // indirect
 	github.com/google/go-cmp v0.6.0 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/google/uuid v1.6.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-sqlite3 v1.14.22 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
-	github.com/openshift/api v0.0.0-20250130171037-7bb8a0201a56 // indirect
+	github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77 // indirect
+	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
-	golang.org/x/net v0.30.0 // indirect
+	go.uber.org/multierr v1.10.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
 	golang.org/x/oauth2 v0.23.0 // indirect
-	golang.org/x/sys v0.26.0 // indirect
-	golang.org/x/term v0.25.0 // indirect
-	golang.org/x/text v0.19.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.7.0 // indirect
 	google.golang.org/protobuf v1.35.1 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/datatypes v1.2.5 // indirect
+	gorm.io/driver/mysql v1.5.6 // indirect
+	gorm.io/driver/sqlite v1.5.7 // indirect
+	gorm.io/gorm v1.25.12 // indirect
 	k8s.io/api v0.32.2 // indirect
 	k8s.io/apimachinery v0.32.2 // indirect
 	k8s.io/klog/v2 v2.130.1 // indirect
Index: /branches/main/array-ingress-controller/controller/openshift-controller/go.sum
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/go.sum	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/go.sum	(working copy)
@@ -1,3 +1,7 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -17,10 +21,19 @@
 github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
 github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
 github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
@@ -31,10 +44,22 @@
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -50,6 +75,10 @@
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
+github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -57,12 +86,12 @@
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
-github.com/openshift/api v0.0.0-20250130171037-7bb8a0201a56 h1:fWNA66LNXugnaxTaRVHZLdW+vbwyk5vwTT9/x2YYiG8=
-github.com/openshift/api v0.0.0-20250130171037-7bb8a0201a56/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77 h1:w6F0sEhlUB1K54Ev4EELsLo5w/xur9pFT19VtemlB4Y=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -87,41 +116,51 @@
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
 golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
-golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
 golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
-golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -135,9 +174,24 @@
 gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
+gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
+gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
+gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
+gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
+gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
+gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
+gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
+gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
 k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
 k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
 k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/endpoint_event_handler.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/endpoint_event_handler.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/endpoint_event_handler.go	(working copy)
@@ -0,0 +1,86 @@
+package handlers
+
+import (
+	"context"
+
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	"arraynetworks.com/array-ingress-controller/task-manager/openshift/apv"
+	"arraynetworks.com/array-ingress-controller/task-manager/openshift/asf"
+	"arraynetworks.com/array-ingress-controller/task-manager/task"
+
+	corev1 "k8s.io/api/core/v1"
+)
+
+func EndPointAdded(obj interface{}){
+
+	endpt := obj.(*corev1.Endpoints)
+
+	routes, err := utils.GetAssocRoutes(endpt.Namespace, endpt.Name)
+	if err != nil || len(routes) == 0 {
+		return
+	}
+
+	// Create OpenShift-specific handlers
+	osAPV := &apv.OpenShiftAPV{}
+	osASF := &asf.OpenShiftASF{}
+
+	// Initialize Task Manager Facade with OpenShift handlers
+	taskManager := task.New(osAPV, osASF)
+	
+	// Create a new task
+	deleteTask := &task.Task{
+		Route:  routes,
+		Svc:    nil,
+		Pods:   nil,
+		EndPts: []*corev1.Endpoints{endpt},
+	}
+
+	ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "ADD")
+	ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "ENDPOINT")
+
+	// Prepare and execute the delete task
+	if err := taskManager.PrepareTask(ctx, deleteTask, "ARRAY-APV"); err != nil {
+		log.Fatalf("Failed to prepare delete task: %v", err)
+	}
+
+	log.Println("Route delete task prepared and executed successfully")
+
+}
+
+func EndPointDeleted(obj interface{}){
+
+	endpt := obj.(*corev1.Endpoints)
+
+	routes, err := utils.GetAssocRoutes(endpt.Namespace, endpt.Name)
+
+	if err != nil || len(routes) == 0 {
+		return
+	}
+
+	// Create OpenShift-specific handlers
+	osAPV := &apv.OpenShiftAPV{}
+	osASF := &asf.OpenShiftASF{}
+
+	// Initialize Task Manager Facade with OpenShift handlers
+	taskManager := task.New(osAPV, osASF)
+	
+	// Create a new task
+	deleteTask := &task.Task{
+		Route:  routes,
+		Svc:    nil,
+		Pods:   nil,
+		EndPts: []*corev1.Endpoints{endpt},
+	}
+
+	ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "DELETE")
+	ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "ENDPOINT")
+
+	// Prepare and execute the delete task
+	if err := taskManager.PrepareTask(ctx, deleteTask, "ARRAY-APV"); err != nil {
+		log.Fatalf("Failed to prepare delete task: %v", err)
+	}
+
+	log.Println("Route delete task prepared and executed successfully")
+
+}
+
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.mod
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.mod	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.mod	(working copy)
@@ -0,0 +1,79 @@
+module arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers
+
+go 1.23.6
+
+replace (
+	arraynetworks.com/array-ingress-controller/configstore => ../../../configstore
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils => ../utils
+	arraynetworks.com/array-ingress-controller/logger => ../../../logger
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv => ../../../task-manager/openshift/apv
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf => ../../../task-manager/openshift/asf
+	arraynetworks.com/array-ingress-controller/task-manager/task => ../../../task-manager/task
+)
+
+require (
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/task-manager/task v0.0.0-00010101000000-000000000000
+	github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77
+	k8s.io/api v0.32.2
+	k8s.io/apimachinery v0.32.2
+)
+
+require (
+	arraynetworks.com/array-ingress-controller/configstore v0.0.0-00010101000000-000000000000 // indirect
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
+	github.com/go-openapi/jsonpointer v0.21.0 // indirect
+	github.com/go-openapi/jsonreference v0.20.2 // indirect
+	github.com/go-openapi/swag v0.23.0 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/google/gnostic-models v0.6.8 // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-sqlite3 v1.14.22 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/x448/float16 v0.8.4 // indirect
+	go.uber.org/multierr v1.10.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
+	golang.org/x/oauth2 v0.23.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
+	golang.org/x/time v0.7.0 // indirect
+	google.golang.org/protobuf v1.35.1 // indirect
+	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/datatypes v1.2.5 // indirect
+	gorm.io/driver/mysql v1.5.6 // indirect
+	gorm.io/driver/sqlite v1.5.7 // indirect
+	gorm.io/gorm v1.25.12 // indirect
+	k8s.io/client-go v0.32.2 // indirect
+	k8s.io/klog/v2 v2.130.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
+	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
+	sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
+	sigs.k8s.io/yaml v1.4.0 // indirect
+)
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.sum
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.sum	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/go.sum	(working copy)
@@ -0,0 +1,212 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
+github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
+github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
+github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77 h1:w6F0sEhlUB1K54Ev4EELsLo5w/xur9pFT19VtemlB4Y=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
+golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
+golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
+google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
+gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
+gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
+gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
+gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
+gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
+gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
+gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
+gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
+gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
+k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
+k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
+k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
+k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/init.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/init.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/init.go	(working copy)
@@ -0,0 +1,37 @@
+/*
+	Copyright 2025 Array Networks
+
+	Licensed 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 handlers
+
+import (
+	"arraynetworks.com/array-ingress-controller/logger"
+)
+
+type taskMap struct {
+	ingressName string
+	protocol    string
+	serviceName string
+	podIPs      []string
+}
+
+var (
+	log      logger.Logger
+)
+
+func init() {
+	log = logger.GetLogger()
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/route_event_handler.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/route_event_handler.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/route_event_handler.go	(working copy)
@@ -0,0 +1,184 @@
+/*
+	Copyright 2025 Array Networks
+
+*/
+
+package handlers
+
+import (
+	"context"
+
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	"arraynetworks.com/array-ingress-controller/task-manager/openshift/apv"
+	"arraynetworks.com/array-ingress-controller/task-manager/openshift/asf"
+	"arraynetworks.com/array-ingress-controller/task-manager/task"
+
+	corev1 "k8s.io/api/core/v1"
+	routev1 "github.com/openshift/api/route/v1"
+)
+
+// RouteAdded handles Route addition events.
+func RouteAdded(obj interface{}) {
+	route := obj.(*routev1.Route)
+	
+	routeClass, flag := utils.CheckRouteClass(*route)
+
+	if !flag {
+		log.Debugf("Ignoring Route: %s/%s\n", route.Namespace, route.Name)
+		return
+	}
+
+	log.Infof("Route Added: %s/%s\n", route.Namespace, route.Name)
+
+	// Get associated service name from route
+	assocSvc, err := utils.GetAssocSvc(route.Namespace, route.Name)
+	if err != nil {
+		log.Errorf("Cannot find service for route '%s' in namespace '%s'", route.Name, route.Namespace)
+		return
+	}
+	log.Infof("Associated realservice: %s", assocSvc)
+	// Get endpoint using service name
+	endpoint, err := utils.GetAssocEndpt(assocSvc, route)
+	if err != nil {
+		log.Errorf("Cannot fetch endpoint '%s' in namespace '%s'", assocSvc, route.Namespace)
+		return
+	}
+	log.Infof("Associated endpoint: %s", endpoint)
+
+	// Create OpenShift-specific handlers
+	osAPV := &apv.OpenShiftAPV{}
+	osASF := &asf.OpenShiftASF{}
+
+	// Initialize Task Manager Facade with OpenShift handlers
+	taskManager := task.New(osAPV, osASF)
+
+	// Create a new task
+	newTask := &task.Task{
+		Route:  []*routev1.Route{route},
+		Svc:    nil,
+		Pods:   nil,
+		EndPts: []*corev1.Endpoints{endpoint},
+	}
+
+	ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "ADD")
+	ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "ROUTE")
+
+	// Prepare a task
+	if err := taskManager.PrepareTask(ctx, newTask, routeClass); err != nil {
+		log.Fatalf("Failed to prepare task: %v", err)
+	}
+	log.Println("Task prepared and executed successfully")
+}
+
+
+func RouteUpdated(oldObj, newObj interface{}) {
+    oldRoute := oldObj.(*routev1.Route)
+    newRoute := newObj.(*routev1.Route)
+
+    
+
+    routeClass, flag := utils.CheckRouteClass(*oldRoute)
+	if !flag {
+		log.Debugf("Ignoring Route: %s/%s\n", oldRoute.Namespace, oldRoute.Name)
+		return
+	}
+	log.Infof("Route updated: %s/%s\n", newRoute.Namespace, oldRoute.Name)
+
+    // Identify if the annotations have been updated
+    annotationsChanged := false
+    if len(oldRoute.Annotations) != len(newRoute.Annotations) {
+        annotationsChanged = true
+    } else {
+        for key, oldValue := range oldRoute.Annotations {
+            if newValue, exists := newRoute.Annotations[key]; !exists || oldValue != newValue {
+                annotationsChanged = true
+                break
+            }
+        }
+    }
+
+    // Log annotation update if detected
+    if annotationsChanged {
+		//WHAT MUST BE DONE?
+        log.Infof("Annotations updated for route %s/%s", newRoute.Namespace, newRoute.Name)
+    }
+
+	// Initialize the Task Manager Facade with OpenShift handlers
+    taskManager := task.New(&apv.OpenShiftAPV{}, &asf.OpenShiftASF{})
+
+    // Create a new task for Route Update
+    newTask := &task.Task{
+        Route:  []*routev1.Route{newRoute},
+        Svc:    nil,
+        Pods:   nil,
+        EndPts: nil,
+    }
+
+	// Set context for task preparation
+    ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "UPDATE")
+    ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "ROUTE")
+
+	// Identify if the path or port has changed
+    if (oldRoute.Spec.Path != newRoute.Spec.Path) || (oldRoute.Spec.Port.TargetPort != newRoute.Spec.Port.TargetPort) {
+        log.Infof("Spec updated for route %s in namespace %s", newRoute.Name, newRoute.Namespace)
+		ctx = context.WithValue(ctx, "spec_updated", "True")
+    }
+
+	healthAnnotChange := utils.CompareJSONAnnotations(oldRoute, newRoute, "arraynetworks.com/healthcheck")
+	if healthAnnotChange {
+		log.Infof("Health Check annotation updated for route %s in namespace %s", newRoute.Name, newRoute.Namespace)
+		ctx = context.WithValue(ctx, "health_check", "True")
+	}
+
+	ratelimitAnnotChang := utils.CompareJSONAnnotations(oldRoute, newRoute, "arraynetworks.com/ratelimit")
+	if ratelimitAnnotChang {
+		log.Infof("Health Check annotation updated for route %s in namespace %s", newRoute.Name, newRoute.Namespace)
+		ctx = context.WithValue(ctx, "ratelimit", "True")
+	}
+
+
+    // Prepare and execute the update task
+    if err := taskManager.PrepareTask(ctx, newTask, routeClass); err != nil {
+        log.Fatalf("Failed to prepare update task: %v", err)
+    }
+
+    log.Println("Route update task prepared and executed successfully")
+}
+
+// RouteDeleted handles Route deletion events.
+func RouteDeleted(obj interface{}) {
+	route := obj.(*routev1.Route)
+	
+	routeClass, flag := utils.CheckRouteClass(*route)
+
+	if !flag {
+		log.Debugf("Ignoring Route: %s/%s\n", route.Namespace, route.Name)
+		return
+	}
+	log.Infof("Route deleted: %s/%s\n", route.Namespace, route.Name)
+
+	// Create OpenShift-specific handlers
+	osAPV := &apv.OpenShiftAPV{}
+	osASF := &asf.OpenShiftASF{}
+
+	// Initialize Task Manager Facade with OpenShift handlers
+	taskManager := task.New(osAPV, osASF)
+
+	// Create a new task
+	deleteTask := &task.Task{
+		Route:  []*routev1.Route{route},
+		Svc:    nil,
+		Pods:   nil,
+		EndPts: nil,
+	}
+
+	ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "DELETE")
+	ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "ROUTE")
+
+	// Prepare and execute the delete task
+	if err := taskManager.PrepareTask(ctx, deleteTask, routeClass); err != nil {
+		log.Fatalf("Failed to prepare delete task: %v", err)
+	}
+
+	log.Println("Route delete task prepared and executed successfully")
+}
Index: /branches/main/array-ingress-controller/controller/openshift-controller/handlers/service_event_handler.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/handlers/service_event_handler.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/handlers/service_event_handler.go	(working copy)
@@ -0,0 +1,98 @@
+/*
+	Copyright 2025 Array Networks
+
+	Licensed 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 handlers
+
+/*
+import (
+	"context"
+
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	"arraynetworks.com/array-ingress-controller/task-manager/openshift"
+	"arraynetworks.com/array-ingress-controller/task-manager/task"
+	v1 "k8s.io/api/core/v1"
+)
+
+// ServiceUpdated handles Service update events.
+func ServiceUpdated(oldObj, newObj interface{}) {
+	oldService := oldObj.(*v1.Service)
+	newService := newObj.(*v1.Service)
+	log.Infof("Service updated: %s/%s\n", newService.Namespace, newService.Name)
+
+	// check if changes in service require changes in configstore
+	selectorChanged := !utils.AreSelectorsEqual(oldService.Spec.Selector, newService.Spec.Selector)
+	portsChanged := !utils.AreServicePortsEqual(oldService.Spec.Ports, newService.Spec.Ports)
+
+	// If nothing significant changed, skip processing
+	if !selectorChanged && !portsChanged {
+		log.Infof("Skipping service update for %s/%s, no relevant changes detected.", newService.Namespace, newService.Name)
+		return
+	}
+
+	// Fetch the associated Route for the updated service
+	assocRoutes, err := utils.GetAssocRoutes(newService.Namespace, newService)
+	if err != nil || len(assocRoutes) == 0 {
+		log.Errorf("Cannot find routes for updated service '%s' in namespace '%s'", newService.Name, newService.Namespace)
+		return
+	}
+
+	// Select the first route (assuming a single route per service)
+	associatedRoute := &assocRoutes[0]
+
+	routeClass, err := utils.GetRouteClass(*associatedRoute)
+	if err != nil {
+		log.Errorf("cannot find class for route '%s'", associatedRoute.Name)
+	}
+
+	var assocPods []*v1.Pod
+
+	if selectorChanged {
+		// Fetch the Pods that match the updated service selector
+		assocPods, err = utils.GetAssocPods(newService.Namespace, newService.Spec.Selector)
+		if err != nil {
+			log.Errorf("Cannot find pods for updated service '%s' in namespace '%s'", newService.Name, newService.Namespace)
+			return
+		}
+	} else {
+		log.Infof("Selector unchanged for service %s, using existing pod records.", newService.Name)
+	}
+
+	// Create OpenShift-specific handlers
+	osAPV := &apv.OpenShiftAPV{}
+	osASF := &asf.OpenShiftASF{}
+
+	// Initialize Task Manager Facade with OpenShift handlers
+	taskManager := task.New(osAPV, osASF)
+
+	// Create a new Task object for service update
+	newTask := &task.Task{
+		Route: &assocRoutes[0],
+		Svc:   newService,
+		Pods:  utils.GetAssocPodPointers(assocPods),
+		EndPts: nil,
+	}
+	ctx := context.WithValue(context.Background(), task.TaskTypeKey{}, "UPDATE")
+	ctx = context.WithValue(ctx, task.ResourceTypeKey{}, "SERVICE")
+
+	// Prepare a task for service update
+	if err := taskManager.PrepareTask(ctx, newTask, routeClass); err != nil {
+		log.Fatalf("Failed to prepare update task: %v", err)
+	}
+
+	log.Println("Service update task prepared and executed successfully")
+}
+	*/
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/endpoint_informer.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/endpoint_informer.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/endpoint_informer.go	(working copy)
@@ -0,0 +1,27 @@
+package informers
+
+import (
+    "arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers"
+    "k8s.io/client-go/informers"
+    "k8s.io/client-go/tools/cache"
+    //corev1 "k8s.io/api/core/v1"
+)
+
+// StartEndpointInformer sets up the Endpoint informer and ensures the cache is synced.
+func StartEndpointInformer(factory informers.SharedInformerFactory, stopCh chan struct{}) {
+    endpointInformer := factory.Core().V1().Endpoints().Informer()
+
+    endpointInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
+        AddFunc:    handlers.EndPointAdded,
+        //UpdateFunc: handlers.EndPointUpdated,
+        DeleteFunc: handlers.EndPointDeleted,
+    })
+
+    go endpointInformer.Run(stopCh)
+
+    if !cache.WaitForCacheSync(stopCh, endpointInformer.HasSynced) {
+        log.Println("Endpoint informer cache sync failed")
+        return
+    }
+    log.Println("Endpoint informer cache synced successfully")
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.mod
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.mod	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.mod	(working copy)
@@ -4,15 +4,17 @@
 
 replace (
 	arraynetworks.com/array-ingress-controller/configstore => ../../../configstore
-	arraynetworks.com/array-ingress-controller/controller/openshift-controller/event-handlers => ../event-handlers
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers => ../handlers
 	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils => ../utils
 	arraynetworks.com/array-ingress-controller/logger => ../../../logger
-	arraynetworks.com/array-ingress-controller/task-manager/openshift => ../../../task-manager/openshift
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv => ../../../task-manager/openshift/apv
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf => ../../../task-manager/openshift/asf
 	arraynetworks.com/array-ingress-controller/task-manager/task => ../../../task-manager/task
 )
 
 require (
-	arraynetworks.com/array-ingress-controller/controller/openshift-controller/event-handlers v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
 	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a
 	k8s.io/client-go v0.32.2
 )
@@ -20,8 +22,8 @@
 require (
 	arraynetworks.com/array-ingress-controller/configstore v0.0.0-00010101000000-000000000000 // indirect
 	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils v0.0.0-00010101000000-000000000000 // indirect
-	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000 // indirect
-	arraynetworks.com/array-ingress-controller/task-manager/openshift v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/apv v0.0.0-00010101000000-000000000000 // indirect
+	arraynetworks.com/array-ingress-controller/task-manager/openshift/asf v0.0.0-00010101000000-000000000000 // indirect
 	arraynetworks.com/array-ingress-controller/task-manager/task v0.0.0-00010101000000-000000000000 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
@@ -48,16 +50,16 @@
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
-	github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3 // indirect
+	github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	go.uber.org/multierr v1.10.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/net v0.30.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
 	golang.org/x/oauth2 v0.23.0 // indirect
-	golang.org/x/sys v0.26.0 // indirect
-	golang.org/x/term v0.25.0 // indirect
-	golang.org/x/text v0.19.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.7.0 // indirect
 	google.golang.org/protobuf v1.35.1 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.sum
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.sum	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/go.sum	(working copy)
@@ -44,8 +44,8 @@
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -86,12 +86,12 @@
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
-github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3 h1:9w+RnW9hOlrtZbvHsBa3GWzWtRJb0XkUBDyQf3DkCGE=
-github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77 h1:w6F0sEhlUB1K54Ev4EELsLo5w/xur9pFT19VtemlB4Y=
+github.com/openshift/api v0.0.0-20250305225826-b8da3bfeaf77/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -125,42 +125,42 @@
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
-golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
 golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
-golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
 golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
-golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/init.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/init.go	(nonexistent)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/init.go	(working copy)
@@ -0,0 +1,30 @@
+/*
+	Copyright 2025 Array Networks
+
+	Licensed 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 informers
+
+ import(
+	 "arraynetworks.com/array-ingress-controller/logger"
+ )
+ 
+ var (
+	 log	        logger.Logger
+ )
+ 
+ func init(){
+	 log	= logger.GetLogger()
+ }
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/route_informer.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/route_informer.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/route_informer.go	(working copy)
@@ -5,10 +5,9 @@
 package informers
 
 import (
-	"log"
 	"time"
 
-	handlers "arraynetworks.com/array-ingress-controller/controller/openshift-controller/event-handlers"
+	handlers "arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers"
 	routev1 "github.com/openshift/client-go/route/clientset/versioned"
 	routeinformers "github.com/openshift/client-go/route/informers/externalversions"
 	"k8s.io/client-go/tools/cache"
@@ -16,9 +15,9 @@
 
 // StartRouteInformer sets up the Route informer and ensures the cache is synced.
 func StartRouteInformer(clientset *routev1.Clientset, stopCh chan struct{}) {
-	factory := routeinformers.NewSharedInformerFactory(clientset, 10*time.Minute)
+	factory := routeinformers.NewSharedInformerFactory(clientset, 1*time.Minute)
 	routeInformer := factory.Route().V1().Routes().Informer()
-
+	log.Info("Starting route Informer")
 	routeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
 		AddFunc:    handlers.RouteAdded,
 		UpdateFunc: handlers.RouteUpdated,
@@ -26,7 +25,6 @@
 	})
 
 	go routeInformer.Run(stopCh)
-
 	if !cache.WaitForCacheSync(stopCh, routeInformer.HasSynced) {
 		log.Println("Route informer cache sync failed")
 		return
Index: /branches/main/array-ingress-controller/controller/openshift-controller/informers/service_informer.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/informers/service_informer.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/informers/service_informer.go	(working copy)
@@ -1,12 +1,12 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
 
 package informers
-
+/*
 import (
     "log"
-    "arraynetworks.com/array-ingress-controller/controller/openshift-controller/event-handlers"
+    "arraynetworks.com/array-ingress-controller/controller/openshift-controller/handlers"
     "k8s.io/client-go/informers"
     "k8s.io/client-go/tools/cache"
 )
@@ -28,4 +28,5 @@
         return
     }
     log.Println("Service informer cache synced successfully")
-}
\ No newline at end of file
+}
+    */
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.mod
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.mod	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.mod	(working copy)
@@ -6,7 +6,7 @@
 
 require (
 	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
-	github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3
+	github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1
 	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a
 	k8s.io/api v0.32.2
 	k8s.io/apimachinery v0.32.2
@@ -22,7 +22,6 @@
 	github.com/go-openapi/jsonreference v0.20.2 // indirect
 	github.com/go-openapi/swag v0.23.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang/mock v1.6.0 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
 	github.com/google/gnostic-models v0.6.8 // indirect
 	github.com/google/go-cmp v0.6.0 // indirect
@@ -38,11 +37,11 @@
 	github.com/x448/float16 v0.8.4 // indirect
 	go.uber.org/multierr v1.10.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/net v0.30.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
 	golang.org/x/oauth2 v0.23.0 // indirect
-	golang.org/x/sys v0.26.0 // indirect
-	golang.org/x/term v0.25.0 // indirect
-	golang.org/x/text v0.19.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	golang.org/x/time v0.7.0 // indirect
 	google.golang.org/protobuf v1.35.1 // indirect
 	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.sum
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.sum	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/go.sum	(working copy)
@@ -33,8 +33,8 @@
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
-github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -59,12 +59,12 @@
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
-github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3 h1:9w+RnW9hOlrtZbvHsBa3GWzWtRJb0XkUBDyQf3DkCGE=
-github.com/openshift/api v0.0.0-20250226153854-e8e096a21cb3/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1 h1:EEiIitbWf/D7MXxpHZc7O0zigK2LNLkjQV91kcT0wHM=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
 github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -89,7 +89,6 @@
 github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
@@ -101,44 +100,36 @@
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
 golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
-golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
 golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
-golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/init.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/init.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/init.go	(working copy)
@@ -1,17 +1,39 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
 
 package utils
 
 import(
+	"sync"
+	"os"
+
 	"arraynetworks.com/array-ingress-controller/logger"
+	"k8s.io/client-go/kubernetes"
+	routev1 "github.com/openshift/client-go/route/clientset/versioned"
 )
 
 var (
-	log	logger.Logger
+	log	        logger.Logger
+	kubeClient  *kubernetes.Clientset
+	routeClient *routev1.Clientset
+	once  sync.Once
 )
 
 func init(){
 	log	= logger.GetLogger()
+
+	var err error
+
+	kubeClient, err = CreateKubeClient()
+    if err != nil {
+        log.Errorf("Error creating Kubernetes client: %v\n", err)
+        os.Exit(1)
+    }
+
+	routeClient, err= CreateRouteClient()
+	if err != nil {
+        log.Errorf("Error creating Kubernetes client: %v\n", err)
+        os.Exit(1)
+    }
 }
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/k8s_helper.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/k8s_helper.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/k8s_helper.go	(working copy)
@@ -6,18 +6,92 @@
 
 import (
 	"context"
+	"encoding/json"
 	"errors"
 	"fmt"
+	"reflect"
 
+	routev1 "github.com/openshift/api/route/v1"
 	corev1 "k8s.io/api/core/v1"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/kubernetes"
 
-	routev1 "github.com/openshift/api/route/v1"
+	"arraynetworks.com/array-ingress-controller/logger"
 )
 
+// Export kubeClient for use in other packages
+var KubeClient *kubernetes.Clientset
+
+func AnnotationExists(route *routev1.Route, annotationKey string) bool {
+	// Retrieve the JSON string from the annotation
+	_, exists := route.Annotations[annotationKey]
+	return exists
+}
+
+func FetchJSONStringFromAnnotation(route *routev1.Route, annotationKey string) (string, bool) {
+
+	// Retrieve the JSON string from the annotation
+	jsonString, exists := route.Annotations[annotationKey]
+	if !exists {
+		logger.Errorf("Annotation '%s' does not exist.\n", annotationKey)
+		return "", exists
+	}
+
+	return jsonString, exists
+}
+
+func CompareJSONAnnotations(oldRoute, newRoute *routev1.Route, annotationKey string) bool {
+	oldAnnotation, oldExists := oldRoute.Annotations[annotationKey]
+	newAnnotation, newExists := newRoute.Annotations[annotationKey]
+
+	if !oldExists && !newExists {
+		logger.Info("Annotation does not exist in either route.")
+		return false
+	}
+
+	if oldAnnotation == newAnnotation {
+		logger.Info("No changes in the annotation.")
+		return false
+	}
+
+	var oldData, newData map[string]interface{}
+
+	if oldExists {
+		if err := json.Unmarshal([]byte(oldAnnotation), &oldData); err != nil {
+			logger.Errorf("Error parsing old annotation JSON:", err)
+			return false
+		}
+	}
+
+	if newExists {
+		if err := json.Unmarshal([]byte(newAnnotation), &newData); err != nil {
+			logger.Errorf("Error parsing new annotation JSON:", err)
+			return false
+		}
+	}
+
+	if !reflect.DeepEqual(oldData, newData) {
+		logger.Info("Annotation fields have changed.")
+		return true
+	}
+
+	return false
+}
+
+func GetRouteProtocol(route *routev1.Route) string {
+	if route.Spec.TLS != nil {
+		return "HTTPS"
+	}
+	return "HTTP"
+}
+
 func GetAssocSvc(namespace, routeName string) (string, error) {
-	route, err := client.Routes(namespace).Get(context.TODO(), routeName, metav1.GetOptions{})
+
+	var err error
+	var route *routev1.Route
+
+	route, err = routeClient.RouteV1().Routes(namespace).Get(context.TODO(), routeName, metav1.GetOptions{})
 	if err != nil {
 		return "", err
 	}
@@ -28,13 +102,26 @@
 }
 
 func GetServicefromName(namespace, serviceName string) (*corev1.Service, error) {
-	service, err := client.Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
+
+	var service *corev1.Service
+	var err error
+
+	service, err = kubeClient.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
 	if err != nil {
 		return nil, err
 	}
+
 	return service, nil
 }
 
+func GetAssocEndpt(serviceName string, route *routev1.Route) (*corev1.Endpoints, error) {
+	endpoint, err := kubeClient.CoreV1().Endpoints(route.Namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return endpoint, nil
+}
+
 func GetAssocPods(namespace string, selectorLabels map[string]string) ([]corev1.Pod, error) {
 
 	// Use the service's selector to list matching pods
@@ -43,7 +130,10 @@
 		LabelSelector: metav1.FormatLabelSelector(&selector),
 	}
 
-	pods, err := client.CoreV1().Pods(namespace).List(context.TODO(), listOptions)
+	var pods *corev1.PodList
+	var err error
+
+	pods, err = kubeClient.CoreV1().Pods(namespace).List(context.TODO(), listOptions)
 	if err != nil {
 		return nil, err
 	}
@@ -60,6 +150,16 @@
 	return podPointers
 }
 
+func CheckRouteClass(route routev1.Route) (string, bool) {
+	// Fetch the annotation value.
+	annotationKey := "arraynetworks.com/class"
+	annotationValue, exists := route.Annotations[annotationKey]
+	if exists && annotationValue == "ARRAY-APV" {
+		return annotationValue, true
+	}
+	return "", false
+}
+
 func GetRouteClass(route routev1.Route) (string, error) {
 	// Fetch the annotation value.
 	annotationKey := "arraynetworks.com/class"
@@ -72,7 +172,11 @@
 
 // GetServiceForPod finds the service that matches the pod's labels.
 func GetServiceForPod(namespace string, podLabels map[string]string) (string, error) {
-	services, err := client.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
+
+	var services *corev1.ServiceList
+	var err error
+
+	services, err = kubeClient.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
 	if err != nil {
 		return "", err
 	}
@@ -94,16 +198,21 @@
 }
 
 // GetAssocRoutes finds routes that point to a given service in a namespace.
-func GetAssocRoutes(namespace string, service *v1.Service) ([]routev1.Route, error) {
-	route, err := client.Routes(namespace).List(context.TODO(), metav1.ListOptions{})
+
+func GetAssocRoutes(namespace string, serviceName string) ([]*routev1.Route, error) {
+	var err error
+	var route *routev1.RouteList
+
+	route, err = routeClient.RouteV1().Routes(namespace).List(context.TODO(), metav1.ListOptions{})
 	if err != nil {
 		return nil, err
 	}
 
-	var assocRoute []routev1.Route
+	var assocRoute []*routev1.Route
 	for _, route := range route.Items {
-		if route.Spec.To.Name == service.Name {
-			assocRoute = append(assocRoute, route)
+		_, flag := CheckRouteClass(route)
+		if flag && (route.Spec.To.Name == serviceName) {
+			assocRoute = append(assocRoute, &route)
 		}
 	}
 
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/kube_client.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/kube_client.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/kube_client.go	(working copy)
@@ -1,31 +1,36 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
 
 package utils
 
 import (
-    "fmt"
     "k8s.io/client-go/kubernetes"
     "k8s.io/client-go/rest"
+
+    "os"
+)
+
+var (
+    initErr     error
 )
 
 // CreateKubeClient creates a Kubernetes client using in-cluster configuration.
 func CreateKubeClient() (*kubernetes.Clientset, error) {
-    once.Do(
-		func() {
-            // Use in-cluster configuration
-            config, err := rest.InClusterConfig()
-            if err != nil {
-                return nil, fmt.Errorf("failed to get in-cluster config: %v", err)
-            }
-
-            // Create the clientset
-            clientset, err := kubernetes.NewForConfig(config)
-            if err != nil {
-                return nil, fmt.Errorf("failed to create Kubernetes client: %v", err)
-            }
-        },
-    )
-    return clientset, nil
+    var config *rest.Config
+    var err error
+    // Use in-cluster configuration
+    config, err = rest.InClusterConfig()
+    if err != nil {
+        initErr = err  
+        log.Error(initErr)
+        os.Exit(1)
+    }
+    // Create the clientset
+    kubeClient, initErr = kubernetes.NewForConfig(config)
+    if initErr != nil {
+        log.Error(initErr)
+        os.Exit(1)
+    }
+    return kubeClient , initErr
 }
\ No newline at end of file
Index: /branches/main/array-ingress-controller/controller/openshift-controller/utils/route_client.go
===================================================================
--- /branches/main/array-ingress-controller/controller/openshift-controller/utils/route_client.go	(revision 9)
+++ /branches/main/array-ingress-controller/controller/openshift-controller/utils/route_client.go	(working copy)
@@ -1,30 +1,33 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
 
 package utils
 
-import (
-    "fmt"
-    "k8s.io/client-go/rest"
-    routev1 "github.com/openshift/client-go/route/clientset/versioned"
-)
+ import (
+     "os"
+ 
+     "k8s.io/client-go/rest"
+     routev1 "github.com/openshift/client-go/route/clientset/versioned"
+ )
+ 
+ var (
+     routeinitErr     error
+ )
+ 
+ // CreateRouteClient creates an OpenShift Route client using in-cluster configuration.
+ func CreateRouteClient() (*routev1.Clientset, error) {
+    config, err := rest.InClusterConfig()
+    if err != nil {
+        routeinitErr = err  
+        log.Error(routeinitErr)
+        os.Exit(1)
+    }
+    routeClient, routeinitErr = routev1.NewForConfig(config)
+    if routeinitErr != nil {
+        log.Error(routeinitErr)
+        os.Exit(1)
+    }
+    return routeClient, routeinitErr 
+ }
 
-// CreateRouteClient creates an OpenShift Route client using in-cluster configuration.
-func CreateRouteClient() (*routev1.Clientset, error) {
-    once.Do(
-		func() {
-            config, err := rest.InClusterConfig()
-            if err != nil {
-                return nil, fmt.Errorf("failed to get in-cluster config: %v", err)
-            }
-
-            clientset, err := routev1.NewForConfig(config)
-            if err != nil {
-                return nil, fmt.Errorf("failed to create OpenShift route client: %v", err)
-            }
-        },
-    )
-
-    return clientset, nil
-}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/logger/consts.go
===================================================================
--- /branches/main/array-ingress-controller/logger/consts.go	(nonexistent)
+++ /branches/main/array-ingress-controller/logger/consts.go	(working copy)
@@ -0,0 +1,20 @@
+package logger
+
+const(
+	// DebugLevel has verbose message
+	DebugLevel = "debug"
+	// InfoLevel is default log level
+	InfoLevel = "info"
+	// WarnLevel is for logging messages about possible issues
+	WarnLevel = "warn"
+	// ErrorLevel is for logging errors
+	ErrorLevel = "error"
+	// FatalLevel is for logging fatal messages.
+	FatalLevel = "fatal"
+
+	InstanceZapLogger int = iota
+
+	TimestampFormat    = "15:04:05.999 02/01/2006 (MST)"
+	DEFAULTLOGFILEPATH = "/var/log/arraycontroller.log"
+	DEFAULTLOGLEVEL    = InfoLevel
+)
\ No newline at end of file
Index: /branches/main/array-ingress-controller/logger/logger.go
===================================================================
--- /branches/main/array-ingress-controller/logger/logger.go	(revision 9)
+++ /branches/main/array-ingress-controller/logger/logger.go	(working copy)
@@ -1,15 +1,14 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
 
 package logger
 
 import (
 	"errors"
-	"io/ioutil"
+	//"io/ioutil"
 	"sync"
-
-	"gopkg.in/yaml.v3"
+	//"gopkg.in/yaml.v3"
 )
 
 var log Logger
@@ -19,32 +18,6 @@
 // Fields Type to pass when we want to call WithFields for structured logging
 type Fields map[string]interface{}
 
-const (
-	// DebugLevel has verbose message
-	DebugLevel = "debug"
-	// InfoLevel is default log level
-	InfoLevel = "info"
-	// WarnLevel is for logging messages about possible issues
-	WarnLevel = "warn"
-	// ErrorLevel is for logging errors
-	ErrorLevel = "error"
-	// FatalLevel is for logging fatal messages.
-	// The system shutsdown after logging the message.
-	FatalLevel = "fatal"
-)
-
-// logger instance
-const (
-	InstanceZapLogger int = iota
-)
-
-// default config log timestamp
-const (
-	TimestampFormat    = "15:04:05.999 02/01/2006 (MST)"
-	DEFAULTLOGFILEPATH = "/var/log/arraycontroller/arraycontroller.log"
-	DEFAULTLOGLEVEL    = InfoLevel
-)
-
 var (
 	errInvalidLoggerInstance = errors.New("Invalid logger instance")
 )
@@ -103,6 +76,7 @@
 	case InstanceZapLogger:
 		logger, err := newZapLogger(config)
 		if err != nil {
+			Panic(err)
 			return err
 		}
 		log = logger
@@ -195,7 +169,7 @@
 // DefaultLoggerConfig is used if default config is not provided
 func DefaultLoggerConfig() Configuration {
 	return Configuration{
-		EnableConsole:     false,
+		EnableConsole:     true,
 		ConsoleLevel:      DEFAULTLOGLEVEL,
 		ConsoleJSONFormat: false,
 		EnableFile:        true,
@@ -209,7 +183,7 @@
 func LoadLogConfig(filepath string) (Configuration, error) {
 
 	logconfig := Configuration{
-		EnableConsole:     false,
+		EnableConsole:     true,
 		ConsoleLevel:      DEFAULTLOGLEVEL,
 		ConsoleJSONFormat: false,
 		EnableFile:        true,
@@ -227,7 +201,7 @@
 	once.Do(
 		func() {
 			var err error
-			config, err = LoadLogConfig()
+			config, err = LoadLogConfig(DEFAULTLOGFILEPATH)
 			if err != nil {
 				config = DefaultLoggerConfig()
 			}
@@ -239,4 +213,4 @@
 		},
 	)
 	return log
-}
\ No newline at end of file
+}
Index: /branches/main/array-ingress-controller/logger/zap.go
===================================================================
--- /branches/main/array-ingress-controller/logger/zap.go	(revision 9)
+++ /branches/main/array-ingress-controller/logger/zap.go	(working copy)
@@ -1,6 +1,6 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
  
 package logger
 
Index: /branches/main/array-ingress-controller/task-manager/kubernetes/apv.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/kubernetes/apv.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/kubernetes/apv.go	(working copy)
@@ -0,0 +1,15 @@
+package kubernetes
+
+import (
+    "taskmanager/pkg/task"
+    "fmt"
+)
+
+// KubernetesAPV implements the APVHandler interface for Kubernetes
+type KubernetesAPV struct{}
+
+func (k *KubernetesAPV) SetupAPV() error {
+    // Kubernetes-specific APV setup logic
+    fmt.Println("Setting up APV on Kubernetes")
+    return nil
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/kubernetes/asf.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/kubernetes/asf.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/kubernetes/asf.go	(working copy)
@@ -0,0 +1,15 @@
+package kubernetes
+
+import (
+    "taskmanager/pkg/task"
+    "fmt"
+)
+
+// KubernetesASF implements the ASFHandler interface for Kubernetes
+type KubernetesASF struct{}
+
+func (k *KubernetesASF) SetupASF() error {
+    // Kubernetes-specific ASF setup logic
+    fmt.Println("Setting up ASF on Kubernetes")
+    return nil
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/apv.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/apv.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/apv.go	(working copy)
@@ -0,0 +1,268 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package apv
+
+import (
+	"context"
+	"fmt"
+
+	//"arraynetworks.com/array-ingress-controller/configstore"
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+	routev1 "github.com/openshift/api/route/v1"
+
+)
+
+type SetUpFunc func(ctx context.Context, task *taskManager.Task) error
+
+// OpenShiftAPV implements the APVHandler interface for OpenShift
+type OpenShiftAPV struct{}
+
+func (o *OpenShiftAPV) SetupAPV(ctx context.Context, task *taskManager.Task) error {
+	// OpenShift-specific APV setup logic
+	log.Info("Setting up APV on OpenShift")
+
+	taskType, _ := ctx.Value(taskManager.TaskTypeKey{}).(string)
+	resourceType, _ := ctx.Value(taskManager.ResourceTypeKey{}).(string)
+
+	key := resourceType + "_" + taskType
+
+	// Lookup the function in the map and execute it if found
+	if handlerFunc, found := apvFunctionMap[key]; found {
+		handlerFunc(ctx, task)
+	} else {
+		return fmt.Errorf("No handler found for: %v", key)
+	}
+	return nil
+}
+
+// Implementations of task handlers
+func handleRouteAdd(ctx context.Context, task *taskManager.Task) error {
+	log.Info("Handling Route Add with additional context data")
+
+	var err error
+
+	//Handle RealService Creation
+	err = addRealService(task)
+	if err != nil {
+		return err
+	}
+
+	// Check if health check annotation exists
+	// If it does, add health check
+	if utils.AnnotationExists(task.Route[0], HealthCheckAnnotKey) {
+		err = addHealthCheck(task)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Check if rate limit annotation exists
+	// If it does, add rate limit
+	if utils.AnnotationExists(task.Route[0], RateLimitAnnotKey) {
+		err = addRateLimit(task)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func handleRouteUpdate(ctx context.Context, task *taskManager.Task) error {
+	var err error
+	// Creating a context with a value
+	value, _ := ctx.Value("spec_updated").(string)
+	if value == "True" {
+		err := updateRealService(task)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Check if health check annotation exists
+	// If it does, update health check
+  
+	if utils.AnnotationExists(task.Route[0], HealthCheckAnnotKey) {
+		err = updateHealthCheck(task)
+		if err != nil {
+			return err
+
+		}
+	}
+
+	// Check if rate limit annotation exists
+	// If it does, update rate limit
+
+	if utils.AnnotationExists(task.Route[0], RateLimitAnnotKey) {
+		err = updateRateLimit(task)
+		if err != nil {
+			return err
+
+		}
+	}
+	return nil
+}
+
+func handleRouteDelete(ctx context.Context, task *taskManager.Task) error {
+	log.Info("Handling Route Delete with additional context data")
+	//Handle RealService Deletion
+	err := deleteRealService(task)
+	if err != nil {
+		return err
+	}
+
+	// Check if health check annotation exists
+	// If it does, delete health check
+	if utils.AnnotationExists(task.Route[0], HealthCheckAnnotKey) {
+		err = deleteHealthCheck(task)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Check if rate limit annotation exists
+	// If it does, delete rate limit
+	if utils.AnnotationExists(task.Route[0], RateLimitAnnotKey) {
+		err = deleteRateLimit(task)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// Endpoint functions
+func handleEndpointAdd(ctx context.Context, task *taskManager.Task) error {
+
+	for _, route := range task.Route {
+
+		var err error
+
+		task.Route = []*routev1.Route{route}
+
+		//Handle RealService Creation
+		err = addRealService(task)
+		if err != nil {
+			return err
+		}
+
+		// Check if health check annotation exists
+		// If it does, add health check
+		if utils.AnnotationExists(route, HealthCheckAnnotKey) {
+			err = addHealthCheck(task)
+			if err != nil {
+				return err
+			}
+		}
+		// Check if rate limit annotation exists
+		// If it does, add rate limit
+		if utils.AnnotationExists(route, RateLimitAnnotKey) {
+			err = addRateLimit(task)
+			if err != nil {
+				return err
+			}
+		}
+
+	}
+
+	return nil
+}
+
+func handleEndpointDelete(ctx context.Context, task *taskManager.Task) error {
+
+	for _, route := range task.Route {
+
+		var err error
+
+		task.Route = []*routev1.Route{route}
+
+		//Handle RealService Creation
+		err = deleteRealService(task)
+		if err != nil {
+			return err
+		}
+
+		// Check if health check annotation exists
+		// If it does, delete health check
+		if utils.AnnotationExists(route, HealthCheckAnnotKey) {
+			err = deleteHealthCheck(task)
+			if err != nil {
+				return err
+			}
+		}
+
+		// Check if rate limit annotation exists
+		// If it does, delete rate limit
+		if utils.AnnotationExists(route, RateLimitAnnotKey) {
+			err = deleteRateLimit(task)
+			if err != nil {
+				return err
+			}
+		}
+
+	}
+
+	return nil
+}
+
+/*
+func handleServiceUpdate(ctx context.Context, task *taskManager.Task) error {
+	log.Info("Handling Service Update with additional context data")
+
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route.Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route.Name, err)
+		return err
+	}
+
+	// Create a map of current Pod IPs for quick lookup
+	currentPodIPs := make(map[string]bool)
+	for _, pod := range task.Pods {
+		currentPodIPs[pod.Status.PodIP] = true
+	}
+
+	// Update service records with new details from updated service
+	for _, service := range realServices {
+		if _, exists := currentPodIPs[service.IPAddress]; exists {
+			// Pod is still part of the service, update only if necessary
+			updatedProtocol := string(task.Svc.Spec.Ports[0].Protocol)
+			updatedPort := int(task.Svc.Spec.Ports[0].Port)
+
+			if service.Protocol != updatedProtocol || service.Port != updatedPort {
+				service.Protocol = updatedProtocol
+				service.Port = updatedPort
+				service.Status = StatusWaiting
+				service.CurrentOp = OperationUpdate
+
+				if err = configStore.Update(service); err != nil {
+					log.Errorf("Error updating service record for %s: %v", service.ServiceName, err)
+					return err
+				} else {
+					log.Infof("Service record updated successfully for %s", service.ServiceName)
+				}
+			}
+		} else {
+			// Pod is no longer part of the service, delete directly
+			if err = configStore.Delete(service); err != nil {
+				log.Error("Error deleting outdated service record for %s: %v", service.ServiceName, err)
+				return err
+			} else {
+				log.Info("Deleted outdated service record for %s", service.ServiceName)
+			}
+		}
+	}
+	return nil
+}
+*/
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/const.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/const.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/const.go	(working copy)
@@ -0,0 +1,58 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package apv
+
+const (
+	StatusWaiting    = "WAITING"
+	StatusInProgress = "INPROGRESS"
+	StatusCompleted  = "COMPLETED"
+	StatusFailed     = "FAILED"
+	StatusDeleted    = "DELETED"
+
+	// Operation types
+	OperationCreate = "CREATE"
+	OperationUpdate = "UPDATE"
+	OperationDelete = "DELETE"
+
+	// Default values
+	DefaultMaxConn = 10
+
+	// Default health check values
+	DefaultHealthCheckType = "http"
+	DefaultHcUp            = 3
+	DefaultHcDown          = 3
+	DefaultSendInterval    = 5 // in seconds
+	DefaultServerTimeout   = 2 // in seconds
+
+	// Default rate limit values
+	DefaultMaxCPS               = 100    // Maximum connections per second
+	DefaultSoftBandwidth        = 1000   // Soft bandwidth limit in kbps
+	DefaultHardBandwidth        = 1500   // Hard bandwidth limit in kbps
+	DefaultServiceType          = "http" // Service type (http, https, tcp, etc.)
+	DefaultServerConnReuse      = true   // Enable server connection reuse
+	DefaultMaxReq               = 1000   // Maximum requests per second
+	DefaultTimeout              = 5000   // Timeout in milliseconds (5s)
+	DefaultServerPersistentConn = true   // Enable server persistent connection
+
+	HealthCheckAnnotKey = "arraynetworks.com/healthcheck"
+	RateLimitAnnotKey   = "arraynetworks.com/ratelimit"
+
+	AsfRealServiceAnnotKey = "arraynetworks.com/asfrealservice"
+	DefaultCheckType = "http"
+)
+
+// Function map to handle different task/resource combinations
+var apvFunctionMap = map[string]SetUpFunc{
+	"ROUTE_ADD":      handleRouteAdd,
+	"ROUTE_UPDATE":   handleRouteUpdate,
+	"ROUTE_DELETE":   handleRouteDelete,
+	"ENDPOINT_ADD":   handleEndpointAdd,
+	//"ENDPOINT_UPDATE": handleEndpointUpdate,
+	"ENDPOINT_DELETE": handleEndpointDelete,
+	//"POD_ADD":        handlePodAdd,
+	//"POD_DELETE":     handlePodDelete,
+	//"SERVICE_UPDATE": handleServiceUpdate,
+}
+
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/go.mod
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/go.mod	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/go.mod	(working copy)
@@ -0,0 +1,75 @@
+module arraynetworks.com/array-ingress-controller/task-manager/openshift/apv
+
+go 1.23.6
+
+replace (
+	arraynetworks.com/array-ingress-controller/configstore => ../../../configstore
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils => ../../../controller/openshift-controller/utils
+	arraynetworks.com/array-ingress-controller/logger => ../../../logger
+	arraynetworks.com/array-ingress-controller/task-manager/task => ../../task
+)
+
+require (
+	arraynetworks.com/array-ingress-controller/configstore v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/task-manager/task v0.0.0-00010101000000-000000000000
+)
+
+require (
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
+	github.com/go-openapi/jsonpointer v0.21.0 // indirect
+	github.com/go-openapi/jsonreference v0.20.2 // indirect
+	github.com/go-openapi/swag v0.23.0 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/google/gnostic-models v0.6.8 // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-sqlite3 v1.14.22 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1 // indirect
+	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/x448/float16 v0.8.4 // indirect
+	go.uber.org/multierr v1.10.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
+	golang.org/x/oauth2 v0.23.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
+	golang.org/x/time v0.7.0 // indirect
+	google.golang.org/protobuf v1.35.1 // indirect
+	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/datatypes v1.2.5 // indirect
+	gorm.io/driver/mysql v1.5.6 // indirect
+	gorm.io/driver/sqlite v1.5.7 // indirect
+	gorm.io/gorm v1.25.12 // indirect
+	k8s.io/api v0.32.2 // indirect
+	k8s.io/apimachinery v0.32.2 // indirect
+	k8s.io/client-go v0.32.2 // indirect
+	k8s.io/klog/v2 v2.130.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
+	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
+	sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
+	sigs.k8s.io/yaml v1.4.0 // indirect
+)
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/go.sum
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/go.sum	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/go.sum	(working copy)
@@ -0,0 +1,212 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
+github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
+github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
+github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1 h1:EEiIitbWf/D7MXxpHZc7O0zigK2LNLkjQV91kcT0wHM=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
+golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
+golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
+google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
+gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
+gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
+gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
+gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
+gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
+gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
+gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
+gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
+gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
+k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
+k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
+k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
+k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/health.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/health.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/health.go	(working copy)
@@ -0,0 +1,185 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package apv
+
+import(
+	"fmt"
+	"encoding/json"
+
+	"arraynetworks.com/array-ingress-controller/configstore"
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+)
+
+type healthCheckAnnotStruct struct{
+	Path         *string `json:"path,omitempty"`
+    Type         *string `json:"type,omitempty"`
+    Method       *string `json:"method,omitempty"`
+    ExpectedCode *string `json:"expected Code,omitempty"`
+    Interval     *int    `json:"interval,omitempty"`
+    Timeout      *int    `json:"timeout,omitempty"`
+    Retries      *int    `json:"retries,omitempty"`
+}
+
+func addHealthCheck(task *taskManager.Task) error {
+	
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], HealthCheckAnnotKey)
+
+	if !exists {
+		return nil
+	}
+
+	// Unmarshal the JSON string into a HealthCheck struct
+    var healthCheckAnnot healthCheckAnnotStruct
+    err = json.Unmarshal([]byte(annots), &healthCheckAnnot)
+    if err != nil {
+        return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+    }
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, realService := range realServices {
+		
+		healthCheck := configstore.HealthCheck{
+			IngressName:   realService.IngressName,
+			HCName:        "hc" + realService.ServiceName,
+			ServiceName:   realService.ServiceName,
+			Type:          getStringValue(healthCheckAnnot.Type, ""),
+			HcUp:          DefaultHcUp,
+			HcDown:        DefaultHcDown,
+			IPv4:          realService.IPAddress,
+			Port:          realService.Port,
+			SendInterval:  getIntValue(healthCheckAnnot.Interval, 3),
+			ServerTimeout: getIntValue(healthCheckAnnot.Timeout, 5),
+			Retries:	   getIntValue(healthCheckAnnot.Retries, 3),
+			Status:        StatusWaiting,
+			CurrentOp:     OperationCreate,
+		}
+
+		if err := configStore.Create(&healthCheck); err != nil {
+			log.Errorf("Error creating health check record for pod %s: %v", realService.ServiceName, err)
+			return err
+		}
+
+		log.Infof("Health check record created successfully for pod %s", realService.ServiceName)
+
+	}
+	
+	return nil
+}
+
+func updateHealthCheck(task *taskManager.Task) error {
+
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], HealthCheckAnnotKey)
+
+	if !exists {
+		return nil
+	}
+
+	// Unmarshal the JSON string into a HealthCheck struct
+    var healthCheckAnnot healthCheckAnnotStruct
+    err = json.Unmarshal([]byte(annots), &healthCheckAnnot)
+    if err != nil {
+        return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+    }
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, realService := range realServices {
+		// TODO: Update only the fields which are changed		
+		healthCheck := configstore.HealthCheck{
+			IngressName:   realService.IngressName,
+			HCName:        "hc" + realService.ServiceName,
+			ServiceName:   realService.ServiceName,
+			Type:          getStringValue(healthCheckAnnot.Type, ""),
+			HcUp:          DefaultHcUp,
+			HcDown:        DefaultHcDown,
+			IPv4:          realService.IPAddress,
+			Port:          realService.Port,
+			SendInterval:  getIntValue(healthCheckAnnot.Interval, 3),
+			ServerTimeout: getIntValue(healthCheckAnnot.Timeout, 5),
+			Retries:	   getIntValue(healthCheckAnnot.Retries, 3),
+			Status:        StatusWaiting,
+			CurrentOp:     OperationUpdate,
+		}
+
+		conditions := map[string]interface{}{
+			"hc_name": healthCheck.HCName,
+		}		
+
+		if err := configStore.Update(&healthCheck, conditions); err != nil {
+			log.Errorf("Error updating health check record for realservice %s: %v", realService.ServiceName, err)
+			return err
+		}
+
+		log.Infof("Health check record updated successfully realservice %s", realService.ServiceName)
+
+	}
+	
+	return nil
+
+}
+
+func deleteHealthCheck(task *taskManager.Task) error {
+	
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Retrieve existing service records
+	var healthchecks []configstore.HealthCheck
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &healthchecks); err != nil {
+		log.Errorf("Error retrieving healthcheck records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, healthcheck := range healthchecks {
+		
+		conditions := map[string]interface{}{
+			"hc_name": healthcheck.HCName,
+		}
+
+		healthcheck.Status = StatusWaiting
+		healthcheck.CurrentOp = OperationDelete
+
+		if err = configStore.Update(&healthcheck, conditions); err != nil {
+			log.Errorf("Error updating service record for %s to status 'delete': %v", healthcheck.ServiceName, err)
+			return err
+		} else {
+			log.Infof("Service record status updated to 'delete' for %s", healthcheck.ServiceName)
+		}
+	}
+
+	return nil
+
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/init.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/init.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/init.go	(working copy)
@@ -0,0 +1,17 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+ package apv
+
+ import(
+	 "arraynetworks.com/array-ingress-controller/logger"
+ )
+ 
+ var (
+	 log	        logger.Logger
+ )
+ 
+ func init(){
+	 log	= logger.GetLogger()
+ }
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/ratelimit.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/ratelimit.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/ratelimit.go	(working copy)
@@ -0,0 +1,178 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package apv
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"arraynetworks.com/array-ingress-controller/configstore"
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+)
+
+type RateLimitAnnotStruct struct {
+	MaxCPS               *int    `json:"max_cps,omitempty"`
+	SoftBW               *int    `json:"soft_bandwidth,omitempty"`
+	HardBW               *int    `json:"hard_bandwidth,omitempty"`
+	ServiceType          *string `json:"service_type,omitempty"`
+	MaxReq               *int    `json:"max_req,omitempty"`
+	Timeout              *int    `json:"time_out,omitempty"`
+	ServerConnReuse      *bool   `json:"server_conn_reuse,omitempty"`
+	ServerPersistentConn *bool   `json:"server_persistent_conn,omitempty"`
+}
+
+func addRateLimit(task *taskManager.Task) error {
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], RateLimitAnnotKey)
+	if !exists {
+		return nil
+	}
+
+	// Unmarshal the JSON string into a HealthCheck struct
+	var rateLimitAnnot RateLimitAnnotStruct
+	err = json.Unmarshal([]byte(annots), &rateLimitAnnot)
+	if err != nil {
+		return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+	}
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, realService := range realServices {
+
+		rateLimit := configstore.RateLimit{
+			IngressName:          realService.IngressName,
+			ServiceName:          realService.ServiceName,
+			MaxCPS:               getIntValue(rateLimitAnnot.MaxCPS, DefaultMaxCPS),
+			SoftBandwidth:        getIntValue(rateLimitAnnot.SoftBW, DefaultSoftBandwidth),
+			HardBandwidth:        getIntValue(rateLimitAnnot.HardBW, DefaultHardBandwidth),
+			ServiceType:          getStringValue(rateLimitAnnot.ServiceType, DefaultServiceType),
+			ServerConnReuse:      getBoolValue(rateLimitAnnot.ServerConnReuse, DefaultServerConnReuse),
+			MaxReq:               getIntValue(rateLimitAnnot.MaxReq, DefaultMaxReq),
+			Timeout:              getIntValue(rateLimitAnnot.Timeout, DefaultTimeout),
+			ServerPersistentConn: getBoolValue(rateLimitAnnot.ServerPersistentConn, DefaultServerPersistentConn),
+			Status:               StatusWaiting,
+			CurrentOp:            OperationCreate,
+		}
+
+		if err := configStore.Create(&rateLimit); err != nil {
+			log.Errorf("Error creating rate limit record for pod %s: %v", realService.ServiceName, err)
+			return err
+		}
+		log.Infof("Health check record created successfully for pod %s", realService.ServiceName)
+	}
+
+	return nil
+}
+
+func updateRateLimit(task *taskManager.Task) error {
+	
+	configStore, err := configstore.Get()
+	
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+	
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], RateLimitAnnotKey)
+	if !exists {
+		return nil
+	}
+	
+	// Unmarshal the JSON string into a HealthCheck struct
+	var rateLimitAnnot RateLimitAnnotStruct
+	
+	err = json.Unmarshal([]byte(annots), &rateLimitAnnot)
+	if err != nil {
+		return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+	}
+	
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+	
+	// Set status to update for each service record
+	for _, realService := range realServices {
+		// TODO: Update only the fields which are changed
+		rateLimit := configstore.RateLimit{
+			IngressName:          realService.IngressName,
+			ServiceName:          realService.ServiceName,
+			MaxCPS:               getIntValue(rateLimitAnnot.MaxCPS, DefaultMaxCPS),
+			SoftBandwidth:        getIntValue(rateLimitAnnot.SoftBW, DefaultSoftBandwidth),
+			HardBandwidth:        getIntValue(rateLimitAnnot.HardBW, DefaultHardBandwidth),
+			ServiceType:          getStringValue(rateLimitAnnot.ServiceType, DefaultServiceType),
+			ServerConnReuse:      getBoolValue(rateLimitAnnot.ServerConnReuse, DefaultServerConnReuse),
+			MaxReq:               getIntValue(rateLimitAnnot.MaxReq, DefaultMaxReq),
+			Timeout:              getIntValue(rateLimitAnnot.Timeout, DefaultTimeout),
+			ServerPersistentConn: getBoolValue(rateLimitAnnot.ServerPersistentConn, DefaultServerPersistentConn),
+			Status:               StatusWaiting,
+			CurrentOp:            OperationUpdate,
+		}
+
+		conditions := map[string]interface{}{
+			"service_name": rateLimit.ServiceName,
+		}
+
+		if err := configStore.Update(&rateLimit, conditions); err != nil {
+			log.Errorf("Error updating rate limit record for realservice %s: %v", realService.ServiceName, err)
+			return err
+		}
+
+		log.Infof("Rate limit record updated successfully realservice %s", realService.ServiceName)
+
+	}
+
+	return nil
+
+}
+
+func deleteRateLimit(task *taskManager.Task) error {
+
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Retrieve existing service records
+	var rateLimits []configstore.RateLimit
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &rateLimits); err != nil {
+		log.Errorf("Error retrieving rate limit records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, rateLimit := range rateLimits {
+		rateLimit.Status = StatusWaiting
+		rateLimit.CurrentOp = OperationDelete
+		conditions := map[string]interface{}{
+			"service_name": rateLimit.ServiceName,
+		}
+		if err = configStore.Update(&rateLimit, conditions); err != nil {
+			log.Errorf("Error updating service record for %s to status '%s': %v", rateLimit.ServiceName, StatusDeleted, err)
+			return err
+		} else {
+			log.Infof("Service record status updated to '%s' for %s", StatusDeleted, rateLimit.ServiceName)
+		}
+	}
+
+	return nil
+
+}
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/realservice.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/realservice.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/realservice.go	(working copy)
@@ -0,0 +1,130 @@
+package apv
+
+import (
+	"fmt"
+	"arraynetworks.com/array-ingress-controller/configstore"
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+)
+
+func addRealService(task *taskManager.Task) error {
+	log.Info("Handling Route Add with additional context data")
+
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Error("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Create a service entry for each endpoint address
+	for _, subset := range task.EndPts[0].Subsets {
+		for _, address := range subset.Addresses {
+
+			realServiceName := fmt.Sprintf("%s_%s_%s", task.Route[0].Name, task.Route[0].Namespace, address.IP) // using format - routename_namespace_endptIP
+			
+			realService := configstore.RealService{
+				IngressName: task.Route[0].Name,
+				ServiceName: realServiceName,
+				Protocol:    utils.GetRouteProtocol(task.Route[0]),
+				IPAddress:   address.IP,
+				IsIP6:       false,
+				Enable:      true,
+				Port:        int(task.Route[0].Spec.Port.TargetPort.IntValue()),
+				MaxConn:     DefaultMaxConn,
+				Status:      StatusWaiting,
+				CurrentOp:   OperationCreate,
+			}
+
+			
+
+			if err = configStore.Create(&realService); err != nil {
+				log.Errorf("Error creating service record for pod %s: %v", realServiceName, err)
+				return err
+			} else {
+				log.Infof("Service record created successfully for pod %s", realServiceName)
+			}
+
+		}
+	}
+	return nil
+}
+
+func deleteRealService(task *taskManager.Task) error {
+	
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Set status to delete for each service record
+	for _, realService := range realServices {
+		
+		conditions := map[string]interface{}{
+			"service_name": realService.ServiceName,
+		}
+
+		realService.Status = StatusWaiting
+		realService.CurrentOp = OperationDelete
+		
+		if err = configStore.Update(&realService, conditions); err != nil {
+			log.Errorf("Error updating service record for %s to status 'delete': %v", realService.ServiceName, err)
+			return err
+		} else {
+			log.Infof("Service record status updated to 'delete' for %s", realService.ServiceName)
+		}
+	}
+
+	return nil
+}
+
+func updateRealService(task *taskManager.Task) error {
+
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		log.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	// Retrieve existing service records
+	var realServices []configstore.RealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		log.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Update service records
+	for _, realService := range realServices {
+		
+		realService.Status = StatusWaiting
+		realService.CurrentOp = OperationUpdate
+		realService.Port = int(task.Route[0].Spec.Port.TargetPort.IntValue())
+		realService.Protocol = utils.GetRouteProtocol(task.Route[0])
+
+		conditions := map[string]interface{}{
+			"service_name": realService.ServiceName,
+		}
+
+		err = configStore.Update(&realService, conditions)
+
+		if err != nil {
+			// todo: check how gorm update works
+			log.Errorf("Error updating service record for %s: %v", realService.ServiceName, err)
+		} else {
+			log.Infof("Service record updated successfully for %s", realService.ServiceName)
+		}
+	}
+
+	return nil
+	
+}
\ No newline at end of file
Index: /branches/main/array-ingress-controller/task-manager/openshift/apv/utils.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/apv/utils.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/apv/utils.go	(working copy)
@@ -0,0 +1,25 @@
+package apv
+
+// Helper function to get string value from a pointer or use a default
+func getStringValue(ptr *string, defaultValue string) string {
+	if ptr != nil {
+		return *ptr
+	}
+	return defaultValue
+}
+
+// Helper function to get int value from a pointer or use a default
+func getIntValue(ptr *int, defaultValue int) int {
+	if ptr != nil {
+		return *ptr
+	}
+	return defaultValue
+}
+
+// Helper function to get bool value from a pointer or use a default
+func getBoolValue(ptr *bool, defaultValue bool) bool {
+	if ptr != nil {
+		return *ptr
+	}
+	return defaultValue
+}
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/asf.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/asf.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/asf.go	(working copy)
@@ -0,0 +1,99 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package asf
+
+import (
+	"context"
+	"fmt"
+
+	"arraynetworks.com/array-ingress-controller/logger"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+	routev1 "github.com/openshift/api/route/v1"
+)
+
+type SetUpFunc func(ctx context.Context, task *taskManager.Task) error
+
+// OpenShiftASF implements the ASFHandler interface for OpenShift
+type OpenShiftASF struct{}
+
+func (o *OpenShiftASF) SetupASF(ctx context.Context, task *taskManager.Task) error {
+	// OpenShift-specific ASF setup logic
+	logger.Info("Setting up ASF on OpenShift")
+
+	taskType, _ := ctx.Value(taskManager.TaskTypeKey{}).(string)
+	resourceType, _ := ctx.Value(taskManager.ResourceTypeKey{}).(string)
+
+	key := resourceType + "_" + taskType
+
+	// Lookup the function in the map and execute it if found
+	if handlerFunc, found := asfFunctionMap[key]; found {
+		handlerFunc(ctx, task)
+	} else {
+		return fmt.Errorf("No handler found for: %v", key)
+	}
+	return nil
+}
+
+// Implementations of task handlers
+func handleRouteAdd(ctx context.Context, task *taskManager.Task) error {
+	logger.Info("Handling Route Add with additional context data")
+	var err error
+	//Handle RealService Creation
+	err = addRealService(task)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func handleRouteUpdate(ctx context.Context, task *taskManager.Task) error {
+	// Creating a context with a value
+	value, _ := ctx.Value("spec_updated").(string)
+	if value == "True" {
+		err := updateRealService(task)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func handleRouteDelete(ctx context.Context, task *taskManager.Task) error {
+	logger.Info("Handling Route Delete with additional context data")
+
+	//Handle RealService Deletion
+	err := deleteRealService(task)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Endpoint functions
+func handleEndpointAdd(ctx context.Context, task *taskManager.Task) error {
+	for _, route := range task.Route {
+		var err error
+		task.Route = []*routev1.Route{route}
+		//Handle RealService Creation
+		err = addRealService(task)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func handleEndpointDelete(ctx context.Context, task *taskManager.Task) error {
+	for _, route := range task.Route {
+		var err error
+		task.Route = []*routev1.Route{route}
+		//Handle RealService Creation
+		err = deleteRealService(task)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/const.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/const.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/const.go	(working copy)
@@ -0,0 +1,39 @@
+/*
+	Copyright 2025 Array Networks
+*/
+
+package asf
+
+const (
+	StatusWaiting    = "WAITING"
+	StatusInProgress = "INPROGRESS"
+	StatusCompleted  = "COMPLETED"
+	StatusFailed     = "FAILED"
+	StatusDeleted    = "DELETED"
+
+	// Operation types
+	OperationCreate = "CREATE"
+	OperationUpdate = "UPDATE"
+	OperationDelete = "DELETE"
+
+	//Default values
+	DefaultServiceType = "http"
+	DefaultHcUp   = 3
+	DefaultHcDown = 3
+
+	AsfRealServiceAnnotKey = "arraynetworks.com/asfrealservice"
+	DefaultCheckType       = "http"
+)
+
+// Function map to handle different task/resource combinations
+var asfFunctionMap = map[string]SetUpFunc{
+	"ROUTE_ADD":    handleRouteAdd,
+	"ROUTE_UPDATE": handleRouteUpdate,
+	"ROUTE_DELETE": handleRouteDelete,
+	// TODO: Uncomment once pod handlers are ready.
+	// "POD_ADD":        handlePodAdd,
+	// "POD_DELETE":     handlePodDelete,
+	// "SERVICE_UPDATE": handleServiceUpdate,
+	"ENDPOINT_ADD":    handleEndpointAdd,
+	"ENDPOINT_DELETE": handleEndpointDelete,
+}
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/go.mod
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/go.mod	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/go.mod	(working copy)
@@ -0,0 +1,75 @@
+module arraynetworks.com/array-ingress-controller/task-manager/openshift/asf
+
+go 1.23.6
+
+replace (
+	arraynetworks.com/array-ingress-controller/configstore => ../../../configstore
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils => ../../../controller/openshift-controller/utils
+	arraynetworks.com/array-ingress-controller/logger => ../../../logger
+	arraynetworks.com/array-ingress-controller/task-manager/task => ../../task
+)
+
+require (
+	arraynetworks.com/array-ingress-controller/configstore v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
+	arraynetworks.com/array-ingress-controller/task-manager/task v0.0.0-00010101000000-000000000000
+	github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1
+)
+
+require (
+	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+	github.com/fxamacker/cbor/v2 v2.7.0 // indirect
+	github.com/go-logr/logr v1.4.2 // indirect
+	github.com/go-openapi/jsonpointer v0.21.0 // indirect
+	github.com/go-openapi/jsonreference v0.20.2 // indirect
+	github.com/go-openapi/swag v0.23.0 // indirect
+	github.com/go-sql-driver/mysql v1.8.1 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/google/gnostic-models v0.6.8 // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/mattn/go-sqlite3 v1.14.22 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/x448/float16 v0.8.4 // indirect
+	go.uber.org/multierr v1.10.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/net v0.33.0 // indirect
+	golang.org/x/oauth2 v0.23.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
+	golang.org/x/time v0.7.0 // indirect
+	google.golang.org/protobuf v1.35.1 // indirect
+	gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
+	gopkg.in/inf.v0 v0.9.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	gorm.io/datatypes v1.2.5 // indirect
+	gorm.io/driver/mysql v1.5.6 // indirect
+	gorm.io/driver/sqlite v1.5.7 // indirect
+	gorm.io/gorm v1.25.12 // indirect
+	k8s.io/api v0.32.2 // indirect
+	k8s.io/apimachinery v0.32.2 // indirect
+	k8s.io/client-go v0.32.2 // indirect
+	k8s.io/klog/v2 v2.130.1 // indirect
+	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
+	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
+	sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
+	sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
+	sigs.k8s.io/yaml v1.4.0 // indirect
+)
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/go.sum
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/go.sum	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/go.sum	(working copy)
@@ -0,0 +1,212 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
+github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
+github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
+github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
+github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
+github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
+github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
+github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
+github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
+github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
+github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
+github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
+github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1 h1:EEiIitbWf/D7MXxpHZc7O0zigK2LNLkjQV91kcT0wHM=
+github.com/openshift/api v0.0.0-20250228110707-635291d6fdf1/go.mod h1:yk60tHAmHhtVpJQo3TwVYq2zpuP70iJIFDCmeKMIzPw=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a h1:duO3JMrUOqVx50QhzxvDeOYIwTNOB8/EEuRLPyvAMBg=
+github.com/openshift/client-go v0.0.0-20250131180035-f7ec47e2d87a/go.mod h1:Qw3ThpzVZ0bfTILpBNYg4LGyjtNxfyCiGh/uDLOOTP8=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
+github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
+golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
+golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
+golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
+google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
+gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/datatypes v1.2.5 h1:9UogU3jkydFVW1bIVVeoYsTpLRgwDVW3rHfJG6/Ek9I=
+gorm.io/datatypes v1.2.5/go.mod h1:I5FUdlKpLb5PMqeMQhm30CQ6jXP8Rj89xkTeCSAaAD4=
+gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
+gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
+gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
+gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
+gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
+gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
+gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
+gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
+gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+k8s.io/api v0.32.2 h1:bZrMLEkgizC24G9eViHGOPbW+aRo9duEISRIJKfdJuw=
+k8s.io/api v0.32.2/go.mod h1:hKlhk4x1sJyYnHENsrdCWw31FEmCijNGPJO5WzHiJ6Y=
+k8s.io/apimachinery v0.32.2 h1:yoQBR9ZGkA6Rgmhbp/yuT9/g+4lxtsGYwW6dR6BDPLQ=
+k8s.io/apimachinery v0.32.2/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.2 h1:4dYCD4Nz+9RApM2b/3BtVvBHw54QjMFUl1OLcJG5yOA=
+k8s.io/client-go v0.32.2/go.mod h1:fpZ4oJXclZ3r2nDOv+Ux3XcJutfrwjKTCHz2H3sww94=
+k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
+k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
+k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
+k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
+sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
+sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
+sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
+sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/realservice.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/realservice.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/realservice.go	(working copy)
@@ -0,0 +1,162 @@
+package asf
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"arraynetworks.com/array-ingress-controller/configstore"
+	"arraynetworks.com/array-ingress-controller/controller/openshift-controller/utils"
+	"arraynetworks.com/array-ingress-controller/logger"
+	taskManager "arraynetworks.com/array-ingress-controller/task-manager/task"
+)
+
+type AsfRealServiceAnnot struct {
+	ServiceType *string `json:"service_type,omitempty"`
+	CheckType   *string `json:"check_type,omitempty"`
+	HCUp        *int    `json:"hc_up,omitempty"`
+	HCDown      *int    `json:"hc_down,omitempty"`
+}
+
+func addRealService(task *taskManager.Task) error {
+	logger.Info("Handling Route Add with additional context data")
+
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		logger.Error("Error initializing config store: %v", err)
+		return err
+	}
+
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], AsfRealServiceAnnotKey)
+
+	if !exists {
+		logger.Warnf("No ASF annotations found for route %s", task.Route[0].Name)
+	}
+
+	// Unmarshal the JSON string into a HealthCheck struct
+	var asfRealServAnnot AsfRealServiceAnnot
+	err = json.Unmarshal([]byte(annots), &asfRealServAnnot)
+	if err != nil {
+		return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+	}
+
+	// Create a service entry for each endpoint address
+	for _, subset := range task.EndPts[0].Subsets {
+		for _, address := range subset.Addresses {
+
+			realServiceName := fmt.Sprintf("%s_%s_%s", task.Route[0].Name, task.Route[0].Namespace, address.IP) // using format - routename_namespace_endptIP
+
+			realService := configstore.AsfRealService{
+				IngressName: task.Route[0].Name,
+				ServiceName: realServiceName,
+				ServiceType: getStringValue(asfRealServAnnot.ServiceType, DefaultServiceType),
+				IPv4:        address.IP,
+				Port:        int(task.Route[0].Spec.Port.TargetPort.IntValue()),
+				CheckType:   getStringValue(asfRealServAnnot.CheckType, DefaultCheckType),
+				HCUp:        getIntValue(asfRealServAnnot.HCUp, DefaultHcUp),
+				HCDown:      getIntValue(asfRealServAnnot.HCDown, DefaultHcDown),
+				Status:      StatusWaiting,
+				CurrentOp:   OperationCreate,
+			}
+			if err = configStore.Create(realService); err != nil {
+				logger.Errorf("Error creating service record for pod %s: %v", realServiceName, err)
+				return err
+			} else {
+				logger.Infof("Service record created successfully for pod %s", realServiceName)
+			}
+		}
+	}
+	return nil
+}
+
+func deleteRealService(task *taskManager.Task) error {
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		logger.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+	// Retrieve existing service records
+	var realServices []configstore.AsfRealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		logger.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+	// Set status to delete for each service record
+	for _, realService := range realServices {
+		realService.Status = StatusDeleted
+
+		conditions := map[string]interface{}{
+			"service_name": realService.ServiceName,
+			// Add more conditions as needed
+		}
+
+		if err = configStore.Update(&realService, conditions); err != nil {
+			logger.Errorf("Error updating service record for %s to status '%s': %v", realService.ServiceName, StatusDeleted, err)
+			return err
+		} else {
+			logger.Infof("Service record status updated to '%s' for %s", StatusDeleted, realService.ServiceName)
+		}
+	}
+	return nil
+}
+
+func updateRealService(task *taskManager.Task) error {
+	// Initialize the config store
+	configStore, err := configstore.Get()
+	if err != nil {
+		logger.Errorf("Error initializing config store: %v", err)
+		return err
+	}
+
+	annots, exists := utils.FetchJSONStringFromAnnotation(task.Route[0], AsfRealServiceAnnotKey)
+
+	if !exists {
+		logger.Warnf("No ASF annotations found for route %s", task.Route[0].Name)
+	}
+
+	// Unmarshal the JSON string into a HealthCheck struct
+	var asfRealServAnnot AsfRealServiceAnnot
+	err = json.Unmarshal([]byte(annots), &asfRealServAnnot)
+	if err != nil {
+		return fmt.Errorf("error unmarshaling JSON from annotation: %v", err)
+	}
+
+	// Retrieve existing service records
+	var realServices []configstore.AsfRealService
+	if err = configStore.ReadByRouteName(task.Route[0].Name, &realServices); err != nil {
+		logger.Errorf("Error retrieving service records for route %s: %v", task.Route[0].Name, err)
+		return err
+	}
+
+	// Update service records
+	for _, realService := range realServices {
+		// TODO: Update only the fields which are changed
+		realService := configstore.AsfRealService{
+			IngressName: task.Route[0].Name,
+			ServiceName: realService.ServiceName,
+			ServiceType: getStringValue(asfRealServAnnot.ServiceType, DefaultServiceType),
+			IPv4:        realService.IPv4,
+			Port:        int(task.Route[0].Spec.Port.TargetPort.IntValue()),
+			CheckType:   getStringValue(asfRealServAnnot.CheckType, DefaultCheckType),
+			HCUp:        getIntValue(asfRealServAnnot.HCUp, DefaultHcUp),
+			HCDown:      getIntValue(asfRealServAnnot.HCDown, DefaultHcDown),
+			Status:      StatusWaiting,
+			CurrentOp:   OperationUpdate,
+		}
+
+		conditions := map[string]interface{}{
+			"service_name": realService.ServiceName,
+			// Add more conditions as needed
+		}
+
+		err = configStore.Update(&realService, conditions)
+		if err != nil {
+			logger.Errorf("Error updating service record for %s: %v", realService.ServiceName, err)
+		} else {
+			logger.Infof("Service record updated successfully for %s", realService.ServiceName)
+		}
+	}
+	return nil
+
+}
Index: /branches/main/array-ingress-controller/task-manager/openshift/asf/utils.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/openshift/asf/utils.go	(nonexistent)
+++ /branches/main/array-ingress-controller/task-manager/openshift/asf/utils.go	(working copy)
@@ -0,0 +1,18 @@
+package asf
+
+// Helper function to get string value from a pointer or use a default
+func getStringValue(ptr *string, defaultValue string) string {
+	if ptr != nil {
+		return *ptr
+	}
+
+	return defaultValue
+}
+
+// Helper function to get int value from a pointer or use a default
+func getIntValue(ptr *int, defaultValue int) int {
+	if ptr != nil {
+		return *ptr
+	}
+	return defaultValue
+}
Index: /branches/main/array-ingress-controller/task-manager/task/interfaces.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/task/interfaces.go	(revision 9)
+++ /branches/main/array-ingress-controller/task-manager/task/interfaces.go	(working copy)
@@ -1,6 +1,6 @@
 /*
 	Copyright 2025 Array Networks
- */
+*/
  
 package task
 
Index: /branches/main/array-ingress-controller/task-manager/task/task.go
===================================================================
--- /branches/main/array-ingress-controller/task-manager/task/task.go	(revision 9)
+++ /branches/main/array-ingress-controller/task-manager/task/task.go	(working copy)
@@ -17,9 +17,10 @@
 
 // Task represents a unit of work with its associated data
 type Task struct {
-	Route *routev1.Route
-	Svc   *corev1.Service
+	Route []*routev1.Route
+	Svc   []*corev1.Service
 	Pods  []*corev1.Pod
+	EndPts []*corev1.Endpoints
 }
 
 // Define custom types for context keys to avoid key collisions
@@ -43,27 +44,27 @@
 
 // PrepareTask prepares a task for execution
 func (t *TaskManagerImpl) PrepareTask(ctx context.Context, task *Task, routeClass string) error {
-	fmt.Println("Preparing task:", task.ID)
-
+	var err error
 	switch routeClass {
-	case "Array-APV":
-		if err := t.apvHandler.SetupAPV(ctx, task); err != nil {
-			fmt.Printf("failed to setup APV: %v\n", err)
-			return err
-		}
-	case "Array-ASF":
-		if err := t.asfHandler.SetupASF(ctx, task); err != nil {
-			fmt.Printf("failed to setup ASF: %v\n", err)
-			return err
-		}
-	default:
-		log.Println("Unknown task")
+		case "ARRAY-APV":
+			if err = t.apvHandler.SetupAPV(ctx, task); err != nil {
+				fmt.Printf("failed to setup APV: %v\n", err)
+				return err
+			}
+		case "ARRAY-ASF":
+			if err = t.asfHandler.SetupASF(ctx, task); err != nil {
+				fmt.Printf("failed to setup ASF: %v\n", err)
+				return err
+			}
+		default:
+			log.Println("Unknown task")
 	}
-
-	return t.dbClient.UpdateTaskStatus(task.ID, task.Status)
+	return err
 }
 
+
 // ExecuteTask executes the prepared task
+/*
 func (t *TaskManagerImpl) ExecuteTask(task *Task) error {
 	fmt.Println("Executing task:", task.ID)
 
@@ -71,3 +72,4 @@
 	task.Status = "Executed"
 	return t.dbClient.UpdateTaskStatus(task.ID, task.Status)
 }
+*/
\ No newline at end of file
Index: /branches/main/array-ingress-controller/watchtower/const.go
===================================================================
--- /branches/main/array-ingress-controller/watchtower/const.go	(nonexistent)
+++ /branches/main/array-ingress-controller/watchtower/const.go	(working copy)
@@ -0,0 +1,6 @@
+package watchtower
+
+const(
+	SMTPServer = "smtp.office365.com"
+	SMTPPort   = 587
+)
\ No newline at end of file
Index: /branches/main/array-ingress-controller/watchtower/email.go
===================================================================
--- /branches/main/array-ingress-controller/watchtower/email.go	(nonexistent)
+++ /branches/main/array-ingress-controller/watchtower/email.go	(working copy)
@@ -0,0 +1,61 @@
+package watchtower
+
+import (
+	"errors"
+	"fmt"
+	"os"
+
+	"gopkg.in/gomail.v2"
+)
+
+// Email struct
+type Email struct {
+	Subject    string
+	Body       string
+	Recipients []string
+	CC         []string
+}
+
+// New initializes and returns an Email instance
+func NewEmail(subject, body string, recipients, cc []string) Email {
+	return Email{
+		Subject:    subject,
+		Body:       body,
+		Recipients: recipients,
+		CC:         cc,
+	}
+}
+
+// Send sends an email using Gomail with environment variables
+func (e *Email) Send() error {
+	// Fetch credentials from environment variables
+	fromEmail := os.Getenv("EMAIL_FROM")
+	password := os.Getenv("EMAIL_PASSWORD") // Auth token works as well
+
+	// Validation: Check for missing values
+	if fromEmail == "" || password == "" {
+		return errors.New("missing EMAIL_FROM or EMAIL_PASSWORD environment variables")
+	}
+	if len(e.Recipients) == 0 {
+		return errors.New("at least one recipient is required")
+	}
+
+	m := gomail.NewMessage()
+	m.SetHeader("From", fromEmail)
+	m.SetHeader("To", e.Recipients...)
+	if len(e.CC) > 0 {
+		m.SetHeader("Cc", e.CC...)
+	}
+	m.SetHeader("Subject", e.Subject)
+	m.SetBody("text/plain", e.Body)
+
+	// Configure the SMTP server
+	d := gomail.NewDialer(SMTPServer, SMTPPort, fromEmail, password)
+
+	// Send the email
+	if err := d.DialAndSend(m); err != nil {
+		return fmt.Errorf("failed to send email: %w", err)
+	}
+
+	return nil
+}
Index: /branches/main/array-ingress-controller/watchtower/go.mod
===================================================================
--- /branches/main/array-ingress-controller/watchtower/go.mod	(nonexistent)
+++ /branches/main/array-ingress-controller/watchtower/go.mod	(working copy)
@@ -0,0 +1,17 @@
+module arraynetworks.com/array-ingress-controller/watchtower
+
+go 1.23.6
+
+replace arraynetworks.com/array-ingress-controller/logger => ../logger
+
+require (
+	arraynetworks.com/array-ingress-controller/logger v0.0.0-00010101000000-000000000000
+	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
+)
+
+require (
+	go.uber.org/multierr v1.10.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
+)
Index: /branches/main/array-ingress-controller/watchtower/go.sum
===================================================================
--- /branches/main/array-ingress-controller/watchtower/go.sum	(nonexistent)
+++ /branches/main/array-ingress-controller/watchtower/go.sum	(working copy)
@@ -0,0 +1,42 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
+github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
+github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
+golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
+gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
+gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Index: /branches/main/array-ingress-controller/watchtower/watchtower.go
===================================================================
--- /branches/main/array-ingress-controller/watchtower/watchtower.go	(nonexistent)
+++ /branches/main/array-ingress-controller/watchtower/watchtower.go	(working copy)
@@ -0,0 +1,186 @@
+package watchtower
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"os/exec"
+	"strings"
+	"time"
+
+	"arraynetworks.com/array-ingress-controller/logger"
+)
+
+var (
+	// Lists of email recipients and CC addresses
+	EmailRecipients = getEmailsFromEnv("EMAIL_RECIPIENTS")
+	EmailCC         = getEmailsFromEnv("EMAIL_CC")
+	PingInterval    = 5 * time.Second
+	FailureLimit    = 3
+	SuccessLimit    = 1
+
+	// APV and ASF monitoring channels
+	APV_IP       = os.Getenv("APV_IP")
+	ASF_IP       = os.Getenv("ASF_IP")
+	APVAvailable = make(chan bool, 1)
+	ASFAvailable = make(chan bool, 1)
+)
+
+// getEmailsFromEnv reads a comma-separated list of emails from an environment variable
+func getEmailsFromEnv(envVar string) []string {
+	val := os.Getenv(envVar)
+	if val == "" {
+		return []string{} // Return empty slice if not set
+	}
+	return strings.Split(val, ",")
+}
+
+// Config holds settings for Watch Tower monitoring
+type Config struct {
+	IP           string
+	PingInterval time.Duration
+	FailureLimit int
+	SuccessLimit int
+	StatusChan   chan bool
+}
+
+// NewConfig returns a default configuration for WatchTower
+func NewConfig(ip string, statusChan chan bool) Config {
+	return Config{
+		IP:           ip,
+		PingInterval: PingInterval,
+		FailureLimit: FailureLimit,
+		SuccessLimit: SuccessLimit,
+		StatusChan:   statusChan,
+	}
+}
+
+// WatchTower monitors the connectivity of device
+type WatchTower struct {
+	config               Config
+	consecutiveFailures  int
+	consecutiveSuccesses int
+	deviceIsDown         bool
+	statusChan           chan bool // true = UP, false = DOWN
+}
+
+// New initializes and returns a new WatchTower instance
+func New(c Config) *WatchTower {
+	return &WatchTower{
+		config:               c,
+		consecutiveFailures:  0,
+		consecutiveSuccesses: 0,
+		deviceIsDown:         false,
+		statusChan:           make(chan bool, 1), // Buffered channel
+	}
+}
+
+// Ping pings the device using the system `Ping` command and only checks for errors
+func (wt *WatchTower) Ping() error {
+	cmd := exec.Command("ping", "-c", "3", "-W", "5", wt.config.IP)
+	output, err := cmd.CombinedOutput()
+
+	if err != nil {
+		return fmt.Errorf("ping failed: %s", strings.TrimSpace(string(output)))
+	}
+	return nil
+}
+
+// Monitor starts monitoring the device connectivity
+func (wt *WatchTower) Monitor(ctx context.Context) {
+	tick := time.Tick(wt.config.PingInterval)
+
+	go func() {
+		defer logger.Info("WatchTower monitoring stopped.")
+
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			case <-tick:
+				// Try to ping the device
+				if err := wt.Ping(); err != nil {
+					wt.consecutiveFailures++
+					wt.consecutiveSuccesses = 0
+
+					logger.WithFields(logger.Fields{
+						"AIP":              wt.config.IP,
+						"Error":            err.Error(),
+						"FailureCount":     wt.consecutiveFailures,
+						"FailureThreshold": wt.config.FailureLimit,
+					}).Error("Device unreachable")
+					// Mark Device as down if failure limit is reached
+					if wt.consecutiveFailures >= wt.config.FailureLimit && !wt.deviceIsDown {
+						wt.deviceIsDown = true
+						DeviceStatus(wt.statusChan, false)
+						wt.SendDownEmail()
+					}
+				} else {
+					wt.consecutiveSuccesses++
+					wt.consecutiveFailures = 0
+					// Mark device as up only after SuccessLimit consecutive successes
+					if wt.deviceIsDown && wt.consecutiveSuccesses >= wt.config.SuccessLimit {
+						wt.deviceIsDown = false
+						DeviceStatus(wt.statusChan, true)
+					}
+				}
+			}
+		}
+	}()
+}
+
+// SendDownEmail sends an email notification when WatchTower goes down
+func (wt *WatchTower) SendDownEmail() {
+	subject := "WatchTower Alert: Device Down"
+	body := fmt.Sprintf("The device at IP %s is down.", wt.config.IP)
+	wt.SendWatchtowerEmail(subject, body)
+}
+
+// SendWatchtowerEmail sends an email using the email package
+func (wt *WatchTower) SendWatchtowerEmail(subject, body string) {
+	emailInstance := NewEmail(
+		subject,
+		body,
+		EmailRecipients,
+		EmailCC,
+	)
+	err := emailInstance.Send()
+	if err != nil {
+		logger.Errorf("Error sending email: %v", err)
+	} else {
+		logger.Infof("Email sent successfully: Subject='%s'", subject)
+	}
+}
+
+// DeviceStatus updates the status channel with the device's availability
+func DeviceStatus(statusChan chan bool, status bool) {
+	select {
+	case statusChan <- status:
+	default:
+	}
+}
+
+// StartMonitoring initializes monitoring for both APV and ASF
+func StartMonitoring(ctx context.Context) {
+	log := logger.GetLogger()
+
+	// Ensure APV and ASF IPs are set
+	if APV_IP == "" || ASF_IP == "" {
+		log.Error("APV_IP or ASF_IP not set in environment variables. Exiting...")
+		return
+	}
+
+	log.Infof("Starting WatchTower Monitoring...")
+
+	// Create configurations for both APV and ASF
+	apvConfig := NewConfig(APV_IP, APVAvailable)
+	asfConfig := NewConfig(ASF_IP, ASFAvailable)
+
+	// Create WatchTower instances
+	apvWatcher := New(apvConfig)
+	asfWatcher := New(asfConfig)
+
+	// Start monitoring both devices
+	go apvWatcher.Monitor(ctx)
+	go asfWatcher.Monitor(ctx)
+}
