@@ -934,7 +934,13 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
934
934
return err
935
935
}
936
936
937
- failForwardEnabled , err := resolver .IsFailForwardEnabled (o .lister .OperatorsV1 ().OperatorGroupLister ().OperatorGroups (namespace ))
937
+ ogLister := o .lister .OperatorsV1 ().OperatorGroupLister ().OperatorGroups (namespace )
938
+ failForwardEnabled , err := resolver .IsFailForwardEnabled (ogLister )
939
+ if err != nil {
940
+ return err
941
+ }
942
+
943
+ unpackTimeout , err := bundle .OperatorGroupBundleUnpackTimeout (ogLister )
938
944
if err != nil {
939
945
return err
940
946
}
@@ -1028,6 +1034,80 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
1028
1034
return err
1029
1035
}
1030
1036
1037
+ // Attempt to unpack bundles before installing
1038
+ // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to.
1039
+ if len (bundleLookups ) > 0 {
1040
+ logger .Debug ("unpacking bundles" )
1041
+
1042
+ var unpacked bool
1043
+ unpacked , steps , bundleLookups , err = o .unpackBundles (namespace , steps , bundleLookups , unpackTimeout )
1044
+ if err != nil {
1045
+ // If the error was fatal capture and fail
1046
+ if olmerrors .IsFatal (err ) {
1047
+ _ , updateErr := o .updateSubscriptionStatuses (
1048
+ o .setSubsCond (subs , v1alpha1.SubscriptionCondition {
1049
+ Type : v1alpha1 .SubscriptionBundleUnpackFailed ,
1050
+ Reason : "ErrorPreventedUnpacking" ,
1051
+ Message : err .Error (),
1052
+ Status : corev1 .ConditionTrue ,
1053
+ }))
1054
+ if updateErr != nil {
1055
+ logger .WithError (updateErr ).Debug ("failed to update subs conditions" )
1056
+ return updateErr
1057
+ }
1058
+ return nil
1059
+ }
1060
+ // Retry sync if non-fatal error
1061
+ return fmt .Errorf ("bundle unpacking failed with an error: %w" , err )
1062
+ }
1063
+
1064
+ // Check BundleLookup status conditions to see if the BundleLookupFailed condtion is true
1065
+ // which means bundle lookup has failed and subscriptions need to be updated
1066
+ // with a condition indicating the failure.
1067
+ isFailed , cond := hasBundleLookupFailureCondition (bundleLookups )
1068
+ if isFailed {
1069
+ err := fmt .Errorf ("bundle unpacking failed. Reason: %v, and Message: %v" , cond .Reason , cond .Message )
1070
+ logger .Infof ("%v" , err )
1071
+
1072
+ _ , updateErr := o .updateSubscriptionStatuses (
1073
+ o .setSubsCond (subs , v1alpha1.SubscriptionCondition {
1074
+ Type : v1alpha1 .SubscriptionBundleUnpackFailed ,
1075
+ Reason : "BundleUnpackFailed" ,
1076
+ Message : err .Error (),
1077
+ Status : corev1 .ConditionTrue ,
1078
+ }))
1079
+ if updateErr != nil {
1080
+ logger .WithError (updateErr ).Debug ("failed to update subs conditions" )
1081
+ return updateErr
1082
+ }
1083
+ // Since this is likely requires intervention we do not want to
1084
+ // requeue too often. We return no error here and rely on a
1085
+ // periodic resync which will help to automatically resolve
1086
+ // some issues such as unreachable bundle images caused by
1087
+ // bad catalog updates.
1088
+ return nil
1089
+ }
1090
+
1091
+ // This means that the unpack job is still running (most likely) or
1092
+ // there was some issue which we did not handle above.
1093
+ if ! unpacked {
1094
+ _ , updateErr := o .updateSubscriptionStatuses (
1095
+ o .setSubsCond (subs , v1alpha1.SubscriptionCondition {
1096
+ Type : v1alpha1 .SubscriptionBundleUnpacking ,
1097
+ Reason : "UnpackingInProgress" ,
1098
+ Status : corev1 .ConditionTrue ,
1099
+ }))
1100
+ if updateErr != nil {
1101
+ logger .WithError (updateErr ).Debug ("failed to update subs conditions" )
1102
+ return updateErr
1103
+ }
1104
+
1105
+ logger .Debug ("unpacking is not complete yet, requeueing" )
1106
+ o .nsResolveQueue .AddAfter (namespace , 5 * time .Second )
1107
+ return nil
1108
+ }
1109
+ }
1110
+
1031
1111
// create installplan if anything updated
1032
1112
if len (updatedSubs ) > 0 {
1033
1113
logger .Debug ("resolution caused subscription changes, creating installplan" )
@@ -1062,8 +1142,17 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
1062
1142
logger .Debugf ("no subscriptions were updated" )
1063
1143
}
1064
1144
1145
+ // Make sure that we no longer indicate unpacking progress
1146
+ subs = o .setSubsCond (subs , v1alpha1.SubscriptionCondition {
1147
+ Type : v1alpha1 .SubscriptionBundleUnpacking ,
1148
+ Status : corev1 .ConditionFalse ,
1149
+ })
1150
+
1151
+ // Remove BundleUnpackFailed condition from subscriptions
1152
+ o .removeSubsCond (subs , v1alpha1 .SubscriptionBundleUnpackFailed )
1153
+
1065
1154
// Remove resolutionfailed condition from subscriptions
1066
- subs = o .removeSubsCond (subs , v1alpha1 .SubscriptionResolutionFailed )
1155
+ o .removeSubsCond (subs , v1alpha1 .SubscriptionResolutionFailed )
1067
1156
newSub := true
1068
1157
for _ , updatedSub := range updatedSubs {
1069
1158
updatedSub .Status .RemoveConditions (v1alpha1 .SubscriptionResolutionFailed )
@@ -1408,19 +1497,27 @@ type UnpackedBundleReference struct {
1408
1497
Properties string `json:"properties"`
1409
1498
}
1410
1499
1411
- func (o * Operator ) unpackBundles (plan * v1alpha1.InstallPlan , unpackTimeout time.Duration ) (bool , * v1alpha1.InstallPlan , error ) {
1412
- out := plan .DeepCopy ()
1500
+ func (o * Operator ) unpackBundles (namespace string , installPlanSteps []* v1alpha1.Step , bundleLookups []v1alpha1.BundleLookup , unpackTimeout time.Duration ) (bool , []* v1alpha1.Step , []v1alpha1.BundleLookup , error ) {
1413
1501
unpacked := true
1414
1502
1503
+ outBundleLookups := make ([]v1alpha1.BundleLookup , len (bundleLookups ))
1504
+ for i := range bundleLookups {
1505
+ bundleLookups [i ].DeepCopyInto (& outBundleLookups [i ])
1506
+ }
1507
+ outInstallPlanSteps := make ([]* v1alpha1.Step , len (installPlanSteps ))
1508
+ for i := range installPlanSteps {
1509
+ outInstallPlanSteps [i ] = installPlanSteps [i ].DeepCopy ()
1510
+ }
1511
+
1415
1512
var errs []error
1416
- for i := 0 ; i < len (out . Status . BundleLookups ); i ++ {
1417
- lookup := out . Status . BundleLookups [i ]
1513
+ for i := 0 ; i < len (outBundleLookups ); i ++ {
1514
+ lookup := outBundleLookups [i ]
1418
1515
res , err := o .bundleUnpacker .UnpackBundle (& lookup , unpackTimeout )
1419
1516
if err != nil {
1420
1517
errs = append (errs , err )
1421
1518
continue
1422
1519
}
1423
- out . Status . BundleLookups [i ] = * res .BundleLookup
1520
+ outBundleLookups [i ] = * res .BundleLookup
1424
1521
1425
1522
// if the failed condition is present it means the bundle unpacking has failed
1426
1523
failedCondition := res .GetCondition (v1alpha1 .BundleLookupFailed )
@@ -1442,11 +1539,11 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan, unpackTimeout time.
1442
1539
continue
1443
1540
}
1444
1541
1445
- // Ensure that bundle can be applied by the current version of OLM by converting to steps
1446
- steps , err := resolver .NewStepsFromBundle (res .Bundle (), out . GetNamespace () , res .Replaces , res .CatalogSourceRef .Name , res .CatalogSourceRef .Namespace )
1542
+ // Ensure that bundle can be applied by the current version of OLM by converting to bundleSteps
1543
+ bundleSteps , err := resolver .NewStepsFromBundle (res .Bundle (), namespace , res .Replaces , res .CatalogSourceRef .Name , res .CatalogSourceRef .Namespace )
1447
1544
if err != nil {
1448
1545
if fatal := olmerrors .IsFatal (err ); fatal {
1449
- return false , nil , err
1546
+ return false , nil , nil , err
1450
1547
}
1451
1548
1452
1549
errs = append (errs , fmt .Errorf ("failed to turn bundle into steps: %v" , err ))
@@ -1455,7 +1552,7 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan, unpackTimeout time.
1455
1552
}
1456
1553
1457
1554
// step manifests are replaced with references to the configmap containing them
1458
- for i , s := range steps {
1555
+ for i , s := range bundleSteps {
1459
1556
ref := UnpackedBundleReference {
1460
1557
Kind : "ConfigMap" ,
1461
1558
Namespace : res .CatalogSourceRef .Namespace ,
@@ -1472,19 +1569,19 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan, unpackTimeout time.
1472
1569
continue
1473
1570
}
1474
1571
s .Resource .Manifest = string (r )
1475
- steps [i ] = s
1572
+ bundleSteps [i ] = s
1476
1573
}
1477
1574
res .RemoveCondition (resolver .BundleLookupConditionPacked )
1478
- out . Status . BundleLookups [i ] = * res .BundleLookup
1479
- out . Status . Plan = append (out . Status . Plan , steps ... )
1575
+ outBundleLookups [i ] = * res .BundleLookup
1576
+ outInstallPlanSteps = append (outInstallPlanSteps , bundleSteps ... )
1480
1577
}
1481
1578
1482
1579
if err := utilerrors .NewAggregate (errs ); err != nil {
1483
1580
o .logger .Debugf ("failed to unpack bundles: %v" , err )
1484
- return false , nil , err
1581
+ return false , nil , nil , err
1485
1582
}
1486
1583
1487
- return unpacked , out , nil
1584
+ return unpacked , outInstallPlanSteps , outBundleLookups , nil
1488
1585
}
1489
1586
1490
1587
// gcInstallPlans garbage collects installplans that are too old
@@ -1631,71 +1728,6 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) {
1631
1728
}
1632
1729
}
1633
1730
1634
- ogLister := o .lister .OperatorsV1 ().OperatorGroupLister ().OperatorGroups (plan .GetNamespace ())
1635
- unpackTimeout , err := bundle .OperatorGroupBundleUnpackTimeout (ogLister )
1636
- if err != nil {
1637
- return err
1638
- }
1639
-
1640
- // Attempt to unpack bundles before installing
1641
- // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to.
1642
- if len (plan .Status .BundleLookups ) > 0 {
1643
- unpacked , out , err := o .unpackBundles (plan , unpackTimeout )
1644
- if err != nil {
1645
- // If the error was fatal capture and fail
1646
- if fatal := olmerrors .IsFatal (err ); fatal {
1647
- if err := o .transitionInstallPlanToFailed (plan , logger , v1alpha1 .InstallPlanReasonInstallCheckFailed , err .Error ()); err != nil {
1648
- // retry for failure to update status
1649
- syncError = err
1650
- return
1651
- }
1652
- }
1653
- // Retry sync if non-fatal error
1654
- syncError = fmt .Errorf ("bundle unpacking failed: %v" , err )
1655
- return
1656
- }
1657
-
1658
- if ! reflect .DeepEqual (plan .Status , out .Status ) {
1659
- logger .Warnf ("status not equal, updating..." )
1660
- if _ , err := o .client .OperatorsV1alpha1 ().InstallPlans (out .GetNamespace ()).UpdateStatus (context .TODO (), out , metav1.UpdateOptions {}); err != nil {
1661
- syncError = fmt .Errorf ("failed to update installplan bundle lookups: %v" , err )
1662
- }
1663
-
1664
- return
1665
- }
1666
-
1667
- // Check BundleLookup status conditions to see if the BundleLookupPending condtion is false
1668
- // which means bundle lookup has failed and the InstallPlan should be failed as well
1669
- isFailed , cond := hasBundleLookupFailureCondition (plan )
1670
- if isFailed {
1671
- err := fmt .Errorf ("bundle unpacking failed. Reason: %v, and Message: %v" , cond .Reason , cond .Message )
1672
- // Mark the InstallPlan as failed for a fatal bundle unpack error
1673
- logger .Infof ("%v" , err )
1674
-
1675
- if err := o .transitionInstallPlanToFailed (plan , logger , v1alpha1 .InstallPlanReasonInstallCheckFailed , err .Error ()); err != nil {
1676
- // retry for failure to update status
1677
- syncError = err
1678
- return
1679
- }
1680
-
1681
- // Requeue subscription to propagate SubscriptionInstallPlanFailed condtion to subscription
1682
- o .requeueSubscriptionForInstallPlan (plan , logger )
1683
- return
1684
- }
1685
-
1686
- // TODO: Remove in favor of job and configmap informer requeuing
1687
- if ! unpacked {
1688
- err := o .ipQueueSet .RequeueAfter (plan .GetNamespace (), plan .GetName (), 5 * time .Second )
1689
- if err != nil {
1690
- syncError = err
1691
- return
1692
- }
1693
- logger .Debug ("install plan not yet populated from bundle image, requeueing" )
1694
-
1695
- return
1696
- }
1697
- }
1698
-
1699
1731
outInstallPlan , syncError := transitionInstallPlanState (logger .Logger , o , * plan , o .now (), o .installPlanTimeout )
1700
1732
1701
1733
if syncError != nil {
@@ -1723,8 +1755,8 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) {
1723
1755
return
1724
1756
}
1725
1757
1726
- func hasBundleLookupFailureCondition (plan * v1alpha1.InstallPlan ) (bool , * v1alpha1.BundleLookupCondition ) {
1727
- for _ , bundleLookup := range plan . Status . BundleLookups {
1758
+ func hasBundleLookupFailureCondition (bundleLookups [] v1alpha1.BundleLookup ) (bool , * v1alpha1.BundleLookupCondition ) {
1759
+ for _ , bundleLookup := range bundleLookups {
1728
1760
for _ , cond := range bundleLookup .Conditions {
1729
1761
if cond .Type == v1alpha1 .BundleLookupFailed && cond .Status == corev1 .ConditionTrue {
1730
1762
return true , & cond
@@ -1734,27 +1766,6 @@ func hasBundleLookupFailureCondition(plan *v1alpha1.InstallPlan) (bool, *v1alpha
1734
1766
return false , nil
1735
1767
}
1736
1768
1737
- func (o * Operator ) transitionInstallPlanToFailed (plan * v1alpha1.InstallPlan , logger logrus.FieldLogger , reason v1alpha1.InstallPlanConditionReason , message string ) error {
1738
- now := o .now ()
1739
- out := plan .DeepCopy ()
1740
- out .Status .SetCondition (v1alpha1 .ConditionFailed (v1alpha1 .InstallPlanInstalled ,
1741
- reason , message , & now ))
1742
- out .Status .Phase = v1alpha1 .InstallPlanPhaseFailed
1743
-
1744
- logger .Info ("transitioning InstallPlan to failed" )
1745
- _ , err := o .client .OperatorsV1alpha1 ().InstallPlans (plan .GetNamespace ()).UpdateStatus (context .TODO (), out , metav1.UpdateOptions {})
1746
- if err == nil {
1747
- return nil
1748
- }
1749
-
1750
- updateErr := errors .New ("error updating InstallPlan status: " + err .Error ())
1751
- logger = logger .WithField ("updateError" , updateErr )
1752
- logger .Errorf ("error transitioning InstallPlan to failed" )
1753
-
1754
- // retry sync with error to update InstallPlan status
1755
- return fmt .Errorf ("installplan failed: %s and error updating InstallPlan status as failed: %s" , message , updateErr )
1756
- }
1757
-
1758
1769
func (o * Operator ) requeueSubscriptionForInstallPlan (plan * v1alpha1.InstallPlan , logger * logrus.Entry ) {
1759
1770
// Notify subscription loop of installplan changes
1760
1771
owners := ownerutil .GetOwnersByKind (plan , v1alpha1 .SubscriptionKind )
0 commit comments