From a0df2989af5e7b0d4a4dee543c6e9d228e99dc9d Mon Sep 17 00:00:00 2001 From: Timofei Larkin Date: Tue, 8 Apr 2025 12:13:26 +0300 Subject: [PATCH] Track public IP usage Signed-off-by: Timofei Larkin --- .../controller/workloadmonitor_controller.go | 74 +++++++++++++++++++ .../templates/dashboard-resourcemap.yaml | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/internal/controller/workloadmonitor_controller.go b/internal/controller/workloadmonitor_controller.go index fbd40ffa..1c23a749 100644 --- a/internal/controller/workloadmonitor_controller.go +++ b/internal/controller/workloadmonitor_controller.go @@ -36,6 +36,11 @@ type WorkloadMonitorReconciler struct { // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch // +kubebuilder:rbac:groups=core,resources=persistentvolumeclaims,verbs=get;list;watch +// isServiceReady checks if the service has an external IP bound +func (r *WorkloadMonitorReconciler) isServiceReady(svc *corev1.Service) bool { + return len(svc.Status.LoadBalancer.Ingress) > 0 +} + // isPVCReady checks if the PVC is bound func (r *WorkloadMonitorReconciler) isPVCReady(pvc *corev1.PersistentVolumeClaim) bool { return pvc.Status.Phase == corev1.ClaimBound @@ -95,6 +100,54 @@ func updateOwnerReferences(obj metav1.Object, monitor client.Object) { obj.SetOwnerReferences(owners) } +// reconcileServiceForMonitor creates or updates a Workload object for the given Service and WorkloadMonitor. +func (r *WorkloadMonitorReconciler) reconcileServiceForMonitor( + ctx context.Context, + monitor *cozyv1alpha1.WorkloadMonitor, + svc corev1.Service, +) error { + logger := log.FromContext(ctx) + workload := &cozyv1alpha1.Workload{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("svc-%s", svc.Name), + Namespace: svc.Namespace, + }, + } + + resources := make(map[string]resource.Quantity) + + q := resource.MustParse("0") + + for _, ing := range svc.Status.LoadBalancer.Ingress { + if ing.IP != "" { + q.Add(resource.MustParse("1")) + } + } + + resources["public-ips"] = q + + _, err := ctrl.CreateOrUpdate(ctx, r.Client, workload, func() error { + // Update owner references with the new monitor + updateOwnerReferences(workload.GetObjectMeta(), monitor) + + workload.Labels = svc.Labels + + // Fill Workload status fields: + workload.Status.Kind = monitor.Spec.Kind + workload.Status.Type = monitor.Spec.Type + workload.Status.Resources = resources + workload.Status.Operational = r.isServiceReady(&svc) + + return nil + }) + if err != nil { + logger.Error(err, "Failed to CreateOrUpdate Workload", "workload", workload.Name) + return err + } + + return nil +} + // reconcilePVCForMonitor creates or updates a Workload object for the given PVC and WorkloadMonitor. func (r *WorkloadMonitorReconciler) reconcilePVCForMonitor( ctx context.Context, @@ -272,6 +325,27 @@ func (r *WorkloadMonitorReconciler) Reconcile(ctx context.Context, req ctrl.Requ } } + svcList := &corev1.ServiceList{} + if err := r.List( + ctx, + svcList, + client.InNamespace(monitor.Namespace), + client.MatchingLabels(monitor.Spec.Selector), + ); err != nil { + logger.Error(err, "Unable to list Services for WorkloadMonitor", "monitor", monitor.Name) + return ctrl.Result{}, err + } + + for _, svc := range svcList.Items { + if svc.Spec.Type != corev1.ServiceTypeLoadBalancer { + continue + } + if err := r.reconcileServiceForMonitor(ctx, monitor, svc); err != nil { + logger.Error(err, "Failed to reconcile Workload for Service", "Service", svc.Name) + continue + } + } + // Update WorkloadMonitor status based on observed pods monitor.Status.ObservedReplicas = observedReplicas monitor.Status.AvailableReplicas = availableReplicas diff --git a/packages/apps/vm-instance/templates/dashboard-resourcemap.yaml b/packages/apps/vm-instance/templates/dashboard-resourcemap.yaml index e1b7242b..d735b5c3 100644 --- a/packages/apps/vm-instance/templates/dashboard-resourcemap.yaml +++ b/packages/apps/vm-instance/templates/dashboard-resourcemap.yaml @@ -22,5 +22,5 @@ spec: kind: virtual-machine type: virtual-machine selector: - vm.kubevirt.io/name: {{ $.Release.Name }} + {{- include "virtual-machine.selectorLabels" . | nindent 4 }} version: {{ $.Chart.Version }}