From 3ef7610a8f591f02cc41020e02118f1a0d0b322e Mon Sep 17 00:00:00 2001 From: Atanas Dinov Date: Wed, 11 Sep 2024 17:35:49 +0300 Subject: [PATCH] Determine supported archs from the release manifest (#79) Signed-off-by: Atanas Dinov --- api/v1alpha1/releasemanifest_types.go | 44 ++++++++++--------- internal/controller/reconcile_os.go | 4 +- internal/controller/reconcile_os_test.go | 6 ++- internal/controller/upgradeplan_controller.go | 21 ++++----- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/api/v1alpha1/releasemanifest_types.go b/api/v1alpha1/releasemanifest_types.go index 35ff5e4..ef9d15c 100644 --- a/api/v1alpha1/releasemanifest_types.go +++ b/api/v1alpha1/releasemanifest_types.go @@ -28,11 +28,30 @@ const ( ArchTypeARM Arch = "aarch64" ) -var SupportedArchitectures = map[string]struct{}{ - string(ArchTypeX86): {}, - string(ArchTypeARM): {}, - ArchTypeX86.Short(): {}, - ArchTypeARM.Short(): {}, +// +kubebuilder:validation:Enum=x86_64;aarch64 +type Arch string + +func (a Arch) Short() string { + switch a { + case ArchTypeX86: + return "amd64" + case ArchTypeARM: + return "arm64" + default: + message := fmt.Sprintf("unknown arch: %s", a) + panic(message) + } +} + +func SupportedArchitectures(architectures []Arch) map[string]struct{} { + supportedArchitectures := map[string]struct{}{} + + for _, a := range architectures { + supportedArchitectures[string(a)] = struct{}{} + supportedArchitectures[a.Short()] = struct{}{} + } + + return supportedArchitectures } // ReleaseManifestSpec defines the desired state of ReleaseManifest @@ -90,21 +109,6 @@ type OperatingSystem struct { PrettyName string `json:"prettyName"` } -// +kubebuilder:validation:Enum=x86_64;aarch64 -type Arch string - -func (a Arch) Short() string { - switch a { - case ArchTypeX86: - return "amd64" - case ArchTypeARM: - return "arm64" - default: - message := fmt.Sprintf("unknown arch: %s", a) - panic(message) - } -} - // +kubebuilder:object:root=true // +kubebuilder:subresource:status diff --git a/internal/controller/reconcile_os.go b/internal/controller/reconcile_os.go index 9ba1e70..5a2698a 100644 --- a/internal/controller/reconcile_os.go +++ b/internal/controller/reconcile_os.go @@ -114,11 +114,11 @@ func isOSUpgraded(nodeList *corev1.NodeList, selector labels.Selector, osPrettyN return true } -func findUnsupportedNodes(nodeList *corev1.NodeList) []string { +func findUnsupportedNodes(nodeList *corev1.NodeList, supportedArchitectures map[string]struct{}) []string { var unsupported []string for _, node := range nodeList.Items { - if _, ok := lifecyclev1alpha1.SupportedArchitectures[node.Status.NodeInfo.Architecture]; !ok { + if _, ok := supportedArchitectures[node.Status.NodeInfo.Architecture]; !ok { unsupported = append(unsupported, node.Name) } } diff --git a/internal/controller/reconcile_os_test.go b/internal/controller/reconcile_os_test.go index ab696a0..d6bfb5e 100644 --- a/internal/controller/reconcile_os_test.go +++ b/internal/controller/reconcile_os_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + lifecyclev1alpha1 "github.com/suse-edge/upgrade-controller/api/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -11,6 +12,9 @@ import ( ) func TestFindUnsupportedNodes(t *testing.T) { + supportedArchitectures := lifecyclev1alpha1.SupportedArchitectures( + []lifecyclev1alpha1.Arch{lifecyclev1alpha1.ArchTypeARM, lifecyclev1alpha1.ArchTypeX86}) + nodes := &corev1.NodeList{ Items: []corev1.Node{ { @@ -39,7 +43,7 @@ func TestFindUnsupportedNodes(t *testing.T) { }, }} - assert.Equal(t, []string{"node1", "node4"}, findUnsupportedNodes(nodes)) + assert.Equal(t, []string{"node1", "node4"}, findUnsupportedNodes(nodes, supportedArchitectures)) } func TestIsOSUpgraded(t *testing.T) { diff --git a/internal/controller/upgradeplan_controller.go b/internal/controller/upgradeplan_controller.go index 97a3254..5a3f731 100644 --- a/internal/controller/upgradeplan_controller.go +++ b/internal/controller/upgradeplan_controller.go @@ -162,12 +162,22 @@ func (r *UpgradePlanReconciler) reconcileDelete(ctx context.Context, upgradePlan } func (r *UpgradePlanReconciler) reconcileNormal(ctx context.Context, upgradePlan *lifecyclev1alpha1.UpgradePlan) (ctrl.Result, error) { + release, err := r.retrieveReleaseManifest(ctx, upgradePlan) + if err != nil { + if !errors.Is(err, errReleaseManifestNotFound) { + return ctrl.Result{}, fmt.Errorf("retrieving release manifest: %w", err) + } + + return ctrl.Result{}, r.createReleaseManifest(ctx, upgradePlan) + } + nodeList := &corev1.NodeList{} if err := r.List(ctx, nodeList); err != nil { return ctrl.Result{}, fmt.Errorf("listing nodes: %w", err) } - if unsupportedNodes := findUnsupportedNodes(nodeList); len(unsupportedNodes) > 0 { + supportedArchitectures := lifecyclev1alpha1.SupportedArchitectures(release.Spec.Components.OperatingSystem.SupportedArchs) + if unsupportedNodes := findUnsupportedNodes(nodeList, supportedArchitectures); len(unsupportedNodes) > 0 { condition := metav1.Condition{ Type: lifecyclev1alpha1.ValidationFailedCondition, Status: metav1.ConditionTrue, @@ -179,15 +189,6 @@ func (r *UpgradePlanReconciler) reconcileNormal(ctx context.Context, upgradePlan return ctrl.Result{}, nil } - release, err := r.retrieveReleaseManifest(ctx, upgradePlan) - if err != nil { - if !errors.Is(err, errReleaseManifestNotFound) { - return ctrl.Result{}, fmt.Errorf("retrieving release manifest: %w", err) - } - - return ctrl.Result{}, r.createReleaseManifest(ctx, upgradePlan) - } - if upgradePlan.Status.ObservedGeneration != upgradePlan.Generation { suffix, err := upgrade.GenerateSuffix() if err != nil {