From 4b5bbf4add78dd4af65cee6b01bd5f2bd75d14f4 Mon Sep 17 00:00:00 2001 From: Ankita Thomas Date: Thu, 7 Mar 2024 15:52:11 -0500 Subject: [PATCH] map kapp conditions to Extension --- api/v1alpha1/clusterextension_types.go | 4 ++ internal/controllers/common_controller.go | 17 +++++ internal/controllers/extension_controller.go | 76 +++++++++++--------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/api/v1alpha1/clusterextension_types.go b/api/v1alpha1/clusterextension_types.go index b763cb60a..72691c058 100644 --- a/api/v1alpha1/clusterextension_types.go +++ b/api/v1alpha1/clusterextension_types.go @@ -77,6 +77,7 @@ const ( // TODO(user): add more Types, here and into init() TypeInstalled = "Installed" TypeResolved = "Resolved" + TypeDeleting = "Deleting" // TypeDeprecated is a rollup condition that is present when // any of the deprecated conditions are present. TypeDeprecated = "Deprecated" @@ -93,6 +94,7 @@ const ( ReasonResolutionUnknown = "ResolutionUnknown" ReasonSuccess = "Success" ReasonDeprecated = "Deprecated" + ReasonDeleteFailed = "DeleteFailed" ) func init() { @@ -104,6 +106,7 @@ func init() { TypePackageDeprecated, TypeChannelDeprecated, TypeBundleDeprecated, + TypeDeleting, ) // TODO(user): add Reasons from above conditionsets.ConditionReasons = append(conditionsets.ConditionReasons, @@ -116,6 +119,7 @@ func init() { ReasonInvalidSpec, ReasonSuccess, ReasonDeprecated, + ReasonDeleteFailed, ) } diff --git a/internal/controllers/common_controller.go b/internal/controllers/common_controller.go index 98067824d..9ac04851d 100644 --- a/internal/controllers/common_controller.go +++ b/internal/controllers/common_controller.go @@ -118,3 +118,20 @@ func setDeprecationStatusesUnknown(conditions *[]metav1.Condition, message strin }) } } + +// setInstalledStatusConditionFailed sets the installed status condition to failed. +func setDeletingStatusConditionFailed(conditions *[]metav1.Condition, message string, generation int64) { + apimeta.SetStatusCondition(conditions, metav1.Condition{ + Type: ocv1alpha1.TypeDeleting, + Status: metav1.ConditionFalse, + Reason: ocv1alpha1.ReasonDeleteFailed, + Message: message, + ObservedGeneration: generation, + }) +} + +// removeAppStatusConditions unsets conditions from App status +func removeAppStatusConditions(conditions *[]metav1.Condition) { + apimeta.RemoveStatusCondition(conditions, ocv1alpha1.TypeDeleting) + apimeta.RemoveStatusCondition(conditions, ocv1alpha1.TypeInstalled) +} diff --git a/internal/controllers/extension_controller.go b/internal/controllers/extension_controller.go index 04310164c..3f382f79e 100644 --- a/internal/controllers/extension_controller.go +++ b/internal/controllers/extension_controller.go @@ -207,7 +207,7 @@ func (r *ExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alpha1.Ext return ctrl.Result{}, err } - mapAppStatusToInstalledCondition(existingTypedApp, ext, bundle.Image) + mapAppStatusToCondition(existingTypedApp, ext, bundle.Image) SetDeprecationStatusInExtension(ext, bundle) return ctrl.Result{}, nil @@ -231,30 +231,47 @@ func (r *ExtensionReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -// TODO: follow up with mapping of all the available App statuses: https://github.com/carvel-dev/kapp-controller/blob/855063edee53315811a13ee8d5df1431ba258ede/pkg/apis/kappctrl/v1alpha1/status.go#L28-L35 -// mapAppStatusToInstalledCondition currently maps only the installed condition. -func mapAppStatusToInstalledCondition(existingApp *kappctrlv1alpha1.App, ext *ocv1alpha1.Extension, bundleImage string) { - appReady := findStatusCondition(existingApp.Status.GenericStatus.Conditions, kappctrlv1alpha1.ReconcileSucceeded) - if appReady == nil { - ext.Status.InstalledBundleResource = "" - setInstalledStatusConditionUnknown(&ext.Status.Conditions, "install status unknown", ext.Generation) - return - } - - if appReady.Status != corev1.ConditionTrue { - ext.Status.InstalledBundleResource = "" - setInstalledStatusConditionFailed( - &ext.Status.Conditions, - appReady.Message, - ext.GetGeneration(), - ) - return +// mapAppStatusToCondition maps the reconciling/deleting App conditions to the installed/deleting conditions on the Extension. +// TODO: suggest using upstream conditions to Carvel. +func mapAppStatusToCondition(existingApp *kappctrlv1alpha1.App, ext *ocv1alpha1.Extension, bundleImage string) { + ext.Status.InstalledBundleResource = "" + message := existingApp.Status.FriendlyDescription + if strings.Contains(message, "Error (see .status.usefulErrorMessage for details)") { + message = existingApp.Status.UsefulErrorMessage + } + + // Remove any existing Reconciled/Deleting conditions + removeAppStatusConditions(&ext.Status.Conditions) + for _, c := range existingApp.Status.GenericStatus.Conditions { + if c.Status == corev1.ConditionTrue { + switch c.Type { + case kappctrlv1alpha1.Reconciling: + setInstalledStatusConditionUnknown(&ext.Status.Conditions, message, ext.Generation) + return + case kappctrlv1alpha1.ReconcileSucceeded: + // InstalledBundleResource this should be converted into a slice as App allows fetching + // from multiple sources. + ext.Status.InstalledBundleResource = bundleImage + setInstalledStatusConditionSuccess(&ext.Status.Conditions, message, ext.Generation) + return + case kappctrlv1alpha1.ReconcileFailed: + if len(message) == 0 { + message = c.Message + } + setInstalledStatusConditionFailed(&ext.Status.Conditions, message, ext.Generation) + return + // case kappctrlv1alpha1.Deleting: + case kappctrlv1alpha1.DeleteFailed: + if len(message) == 0 { + message = c.Message + } + setDeletingStatusConditionFailed(&ext.Status.Conditions, message, ext.Generation) + return + } + } } - - // InstalledBundleResource this should be converted into a slice as App allows fetching - // from multiple sources. - ext.Status.InstalledBundleResource = bundleImage - setInstalledStatusConditionSuccess(&ext.Status.Conditions, appReady.Message, ext.Generation) + setInstalledStatusConditionUnknown(&ext.Status.Conditions, "install status unknown", ext.Generation) + return } // setDeprecationStatus will set the appropriate deprecation statuses for a Extension @@ -339,17 +356,6 @@ func SetDeprecationStatusInExtension(ext *ocv1alpha1.Extension, bundle *catalogm } } -// findStatusCondition finds the conditionType in conditions. -// TODO: suggest using upstream conditions to Carvel. -func findStatusCondition(conditions []kappctrlv1alpha1.Condition, conditionType kappctrlv1alpha1.ConditionType) *kappctrlv1alpha1.Condition { - for i := range conditions { - if conditions[i].Type == conditionType { - return &conditions[i] - } - } - return nil -} - func (r *ExtensionReconciler) ensureApp(ctx context.Context, desiredApp *unstructured.Unstructured) error { existingApp, err := r.existingAppUnstructured(ctx, desiredApp.GetName(), desiredApp.GetNamespace()) if client.IgnoreNotFound(err) != nil {