Skip to content

Commit

Permalink
POC: block operator upgrade when detecting outdated vms
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Sionov <[email protected]>
  • Loading branch information
dasionov committed Nov 21, 2024
1 parent b974705 commit eefac66
Showing 1 changed file with 83 additions and 0 deletions.
83 changes: 83 additions & 0 deletions controllers/hyperconverged/hyperconverged_controller.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package hyperconverged

import (
"bufio"
"cmp"
"context"
"crypto/tls"
"encoding/json"
"fmt"
"net/http"
"os"
"reflect"
"regexp"
"slices"

"github.com/blang/semver/v4"
Expand Down Expand Up @@ -101,6 +105,8 @@ var JSONPatchAnnotationNames = []string{
common.JSONPatchSSPAnnotationName,
}

var rhel8Regex = regexp.MustCompile(`.*rhel8.*`)

Check failure on line 108 in controllers/hyperconverged/hyperconverged_controller.go

View workflow job for this annotation

GitHub Actions / linter Checks

var `rhel8Regex` is unused (unused)

// RegisterReconciler creates a new HyperConverged Reconciler and registers it into manager.
func RegisterReconciler(mgr manager.Manager, ci hcoutil.ClusterInfo, upgradeableCond hcoutil.Condition) error {
return add(mgr, newReconciler(mgr, ci, upgradeableCond), ci)
Expand Down Expand Up @@ -336,6 +342,11 @@ func (r *ReconcileHyperConverged) Reconcile(ctx context.Context, request reconci
return result, err
}

err = r.evaluateUpgradeEligibility(hcoRequest)
if err != nil {
hcoRequest.Logger.Error(err, "Failed to evaluate upgrade eligibility", "err", err)
return reconcile.Result{}, err
}
if err = r.setOperatorUpgradeableStatus(hcoRequest); err != nil {
return reconcile.Result{}, err
}
Expand Down Expand Up @@ -1330,6 +1341,78 @@ func (r *ReconcileHyperConverged) deleteObj(req *common.HcoRequest, obj client.O
return removed, nil
}

func (r *ReconcileHyperConverged) evaluateUpgradeEligibility(req *common.HcoRequest) error {

rhel8Regex := regexp.MustCompile(`.*rhel8.*`)

podList := &corev1.PodList{}
listOpts := []client.ListOption{
client.InNamespace(req.Namespace),
client.MatchingLabels{"kubevirt.io": "virt-controller"},
}

if err := r.client.List(req.Ctx, podList, listOpts...); err != nil {
req.Logger.Info("Failed to list virt-controller pods", "namespace", req.Namespace, "error", err)
return fmt.Errorf("failed to list virt-controller pods: %w", err)
}

if len(podList.Items) == 0 {
req.Logger.Info("No virt-controller pods found", "namespace", req.Namespace)
return nil
}

httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}

for _, pod := range podList.Items {
if pod.Status.PodIP == "" {
continue
}

if err := r.checkPodMetrics(req, httpClient, pod, rhel8Regex); err != nil {
req.Logger.Info("Error processing pod metrics", "pod", pod.Name, "error", err)
}
}

return nil
}

func (r *ReconcileHyperConverged) checkPodMetrics(req *common.HcoRequest, httpClient *http.Client, pod corev1.Pod, rhel8Regex *regexp.Regexp) error {
metricsURL := fmt.Sprintf("https://%s:%d/metrics", pod.Status.PodIP, 8443)

resp, err := httpClient.Get(metricsURL)
if err != nil {
req.Logger.Info("Failed to query metrics from pod", "pod", pod.Name, "error", err)
return fmt.Errorf("failed to query metrics: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
req.Logger.Info("Metrics endpoint returned error", "pod", pod.Name, "status", resp.StatusCode)
return fmt.Errorf("metrics endpoint returned status %d", resp.StatusCode)
}

scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
line := scanner.Text()
if rhel8Regex.MatchString(line) {
req.Logger.Info("Detected outdated machine type in metrics", "pod", pod.Name, "matched", rhel8Regex.FindString(line))
req.Upgradeable = false
return nil
}
}

if err := scanner.Err(); err != nil {
req.Logger.Info("Failed to scan metrics response from pod", "pod", pod.Name, "error", err)
return fmt.Errorf("failed to scan metrics response: %w", err)
}

return nil
}

func removeOldQuickStartGuides(req *common.HcoRequest, cl client.Client, requiredQSList []string) {
existingQSList := &consolev1.ConsoleQuickStartList{}
req.Logger.Info("reading quickstart guides")
Expand Down

0 comments on commit eefac66

Please sign in to comment.