@@ -53,6 +53,7 @@ import (
53
53
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped"
54
54
sharedtime "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/time"
55
55
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
56
+ "github.com/operator-framework/operator-registry/pkg/configmap"
56
57
)
57
58
58
59
const (
@@ -1105,9 +1106,20 @@ func (o *Operator) createInstallPlan(namespace string, gen int, subs []*v1alpha1
1105
1106
return reference .GetReference (res )
1106
1107
}
1107
1108
1109
+ type UnpackedBundleReference struct {
1110
+ Kind string `json:"kind"`
1111
+ Name string `json:"name"`
1112
+ Namespace string `json:"namespace"`
1113
+ CatalogSourceName string `json:"catalogSourceName"`
1114
+ CatalogSourceNamespace string `json:"catalogSourceNamespace"`
1115
+ Replaces string `json:"replaces"`
1116
+ }
1117
+
1118
+ // unpackBundles makes one walk through the bundlelookups and attempts to progress them
1108
1119
func (o * Operator ) unpackBundles (plan * v1alpha1.InstallPlan ) (bool , * v1alpha1.InstallPlan , error ) {
1109
1120
out := plan .DeepCopy ()
1110
1121
unpacked := true
1122
+ unpackedCount := len (out .Status .BundleLookups )
1111
1123
1112
1124
var errs []error
1113
1125
for i := 0 ; i < len (out .Status .BundleLookups ); i ++ {
@@ -1117,32 +1129,55 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In
1117
1129
errs = append (errs , err )
1118
1130
continue
1119
1131
}
1132
+ out .Status .BundleLookups [i ] = * res .BundleLookup
1120
1133
1121
- if res == nil {
1134
+ // if pending condition is present, still waiting for the job to unpack to configmap
1135
+ if res .GetCondition (v1alpha1 .BundleLookupPending ).Status == corev1 .ConditionTrue {
1122
1136
unpacked = false
1123
1137
continue
1124
1138
}
1125
1139
1126
- out . Status . BundleLookups [ i ] = * res . BundleLookup
1127
- if res .Bundle () == nil || len ( res . Bundle (). GetObject ()) == 0 {
1128
- unpacked = false
1140
+ // if packed condition is missing, bundle has already been unpacked into steps, continue
1141
+ if res .GetCondition ( resolver . BundleLookupConditionPacked ). Status == corev1 . ConditionUnknown {
1142
+ unpackedCount --
1129
1143
continue
1130
1144
}
1131
1145
1146
+ // Ensure that bundle can be applied by the current version of OLM by converting to steps
1132
1147
steps , err := resolver .NewStepsFromBundle (res .Bundle (), out .GetNamespace (), res .Replaces , res .CatalogSourceRef .Name , res .CatalogSourceRef .Namespace )
1133
1148
if err != nil {
1134
- errs = append (errs , fmt .Errorf ("failed to turn bundle into steps: %s " , err . Error () ))
1149
+ errs = append (errs , fmt .Errorf ("failed to turn bundle into steps: %v " , err ))
1135
1150
unpacked = false
1136
1151
continue
1137
1152
}
1138
1153
1139
- // Add steps and remove resolved bundle lookup
1154
+ // step manifests are replaced with references to the configmap containing them
1155
+ for i , s := range steps {
1156
+ ref := UnpackedBundleReference {
1157
+ Kind : "ConfigMap" ,
1158
+ Namespace : res .CatalogSourceRef .Namespace ,
1159
+ Name : res .Name (),
1160
+ CatalogSourceName : res .CatalogSourceRef .Name ,
1161
+ CatalogSourceNamespace : res .CatalogSourceRef .Namespace ,
1162
+ Replaces : res .Replaces ,
1163
+ }
1164
+ r , err := json .Marshal (& ref )
1165
+ if err != nil {
1166
+ errs = append (errs , fmt .Errorf ("failed to generate reference for configmap: %v" , err ))
1167
+ unpacked = false
1168
+ continue
1169
+ }
1170
+ s .Resource .Manifest = string (r )
1171
+ steps [i ] = s
1172
+ }
1173
+ unpackedCount --
1174
+ res .RemoveCondition (resolver .BundleLookupConditionPacked )
1175
+ out .Status .BundleLookups [i ] = * res .BundleLookup
1140
1176
out .Status .Plan = append (out .Status .Plan , steps ... )
1141
- out .Status .BundleLookups = append (out .Status .BundleLookups [:i ], out .Status .BundleLookups [i + 1 :]... )
1142
- i --
1143
1177
}
1144
1178
1145
1179
if err := utilerrors .NewAggregate (errs ); err != nil {
1180
+ o .logger .Debugf ("failed to unpack bundles: %v" , err )
1146
1181
return false , nil , err
1147
1182
}
1148
1183
@@ -1418,9 +1453,79 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1418
1453
ensurer := newStepEnsurer (kubeclient , crclient , dynamicClient )
1419
1454
b := newBuilder (kubeclient , dynamicClient , o .csvProvidedAPIsIndexer , o .logger )
1420
1455
1456
+ refForStep := func (step * v1alpha1.Step ) * UnpackedBundleReference {
1457
+ log := o .logger .WithFields (logrus.Fields {"resolving" : step .Resolving , "step" : step .Resource .Name })
1458
+ var ref UnpackedBundleReference
1459
+ if err := json .Unmarshal ([]byte (step .Resource .Manifest ), & ref ); err != nil {
1460
+ log .Debug ("step is not a reference to an unpacked bundle (this is not an error if the step is a manifest)" )
1461
+ return nil
1462
+ }
1463
+ log = log .WithField ("ref" , ref )
1464
+ if ref .Kind != "ConfigMap" || ref .Name == "" || ref .Namespace == "" || ref .CatalogSourceName == "" || ref .CatalogSourceNamespace == "" {
1465
+ log .Debug ("step is not a reference to an unpacked bundle (this is not an error if the step is a manifest)" )
1466
+ return nil
1467
+ }
1468
+ return & ref
1469
+ }
1470
+
1471
+ // for each step that points to a configmap instead of holding the full step manifest, find the steps and cache them
1472
+ unpackedSteps := map [string ][]v1alpha1.StepResource {}
1473
+ loader := configmap .NewBundleLoader ()
1474
+ for _ , step := range plan .Status .Plan {
1475
+ ref := refForStep (step )
1476
+ if ref == nil {
1477
+ continue
1478
+ }
1479
+ cm , err := o .lister .CoreV1 ().ConfigMapLister ().ConfigMaps (ref .Namespace ).Get (ref .Name )
1480
+ if err != nil {
1481
+ return errorwrap .Wrapf (err , "error finding unpacked bundle configmap for ref %s" , step .Resource .Manifest )
1482
+ }
1483
+ b , err := loader .Load (cm )
1484
+ if err != nil {
1485
+ return errorwrap .Wrapf (err , "error loading unpacked bundle configmap for ref %s" , step .Resource .Manifest )
1486
+ }
1487
+ steps , err := resolver .NewStepResourceFromBundle (b , plan .GetNamespace (), ref .Replaces , ref .CatalogSourceName , ref .CatalogSourceNamespace )
1488
+ if err != nil {
1489
+ return errorwrap .Wrapf (err , "error calculating steps for ref %s" , step .Resource .Manifest )
1490
+ }
1491
+ unpackedSteps [step .Resolving ] = steps
1492
+ }
1493
+
1494
+ manifestForStep := func (step * v1alpha1.Step ) (string , error ) {
1495
+ manifest := step .Resource .Manifest
1496
+ ref := refForStep (step )
1497
+ if ref != nil {
1498
+ log := o .logger .WithFields (logrus.Fields {"resolving" : step .Resolving , "step" : step .Resource .Name })
1499
+ log .WithField ("ref" , ref ).Debug ("step is a reference to configmap" )
1500
+ if usteps , ok := unpackedSteps [step .Resolving ]; ok {
1501
+ log .Debugf ("checking cache for unpacked step" )
1502
+ // need to find the real manifest from the unpacked steps
1503
+ for _ , u := range usteps {
1504
+ if u .Name == step .Resource .Name &&
1505
+ u .Kind == step .Resource .Kind &&
1506
+ u .Version == step .Resource .Version &&
1507
+ u .Group == step .Resource .Group {
1508
+ manifest = u .Manifest
1509
+ log .WithField ("manifest" , manifest ).Debug ("step replaced with unpacked value" )
1510
+ }
1511
+ }
1512
+ }
1513
+ if manifest == step .Resource .Manifest {
1514
+ return "" , errorwrap .Wrapf (err , "couldn't find unpacked step for %v" , step )
1515
+ }
1516
+ }
1517
+ return manifest , nil
1518
+ }
1519
+
1421
1520
for i , step := range plan .Status .Plan {
1521
+ // TODO: should lazy load only when the manifest is actually needed
1522
+ manifest , err := manifestForStep (step )
1523
+ if err != nil {
1524
+ return err
1525
+ }
1526
+
1422
1527
doStep := true
1423
- s , err := b .create (step )
1528
+ s , err := b .create (step , manifest )
1424
1529
if err != nil {
1425
1530
if _ , ok := err .(notSupportedStepperErr ); ok {
1426
1531
// stepper not implemented for this type yet
@@ -1448,7 +1553,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1448
1553
case v1alpha1 .ClusterServiceVersionKind :
1449
1554
// Marshal the manifest into a CSV instance.
1450
1555
var csv v1alpha1.ClusterServiceVersion
1451
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & csv )
1556
+ err := json .Unmarshal ([]byte (manifest ), & csv )
1452
1557
if err != nil {
1453
1558
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1454
1559
}
@@ -1481,7 +1586,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1481
1586
case v1alpha1 .SubscriptionKind :
1482
1587
// Marshal the manifest into a subscription instance.
1483
1588
var sub v1alpha1.Subscription
1484
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & sub )
1589
+ err := json .Unmarshal ([]byte (manifest ), & sub )
1485
1590
if err != nil {
1486
1591
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1487
1592
}
@@ -1505,7 +1610,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1505
1610
1506
1611
case resolver .BundleSecretKind :
1507
1612
var s corev1.Secret
1508
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & s )
1613
+ err := json .Unmarshal ([]byte (manifest ), & s )
1509
1614
if err != nil {
1510
1615
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1511
1616
}
@@ -1544,7 +1649,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1544
1649
case clusterRoleKind :
1545
1650
// Marshal the manifest into a ClusterRole instance.
1546
1651
var cr rbacv1.ClusterRole
1547
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & cr )
1652
+ err := json .Unmarshal ([]byte (manifest ), & cr )
1548
1653
if err != nil {
1549
1654
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1550
1655
}
@@ -1559,7 +1664,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1559
1664
case clusterRoleBindingKind :
1560
1665
// Marshal the manifest into a RoleBinding instance.
1561
1666
var rb rbacv1.ClusterRoleBinding
1562
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & rb )
1667
+ err := json .Unmarshal ([]byte (manifest ), & rb )
1563
1668
if err != nil {
1564
1669
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1565
1670
}
@@ -1574,7 +1679,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1574
1679
case roleKind :
1575
1680
// Marshal the manifest into a Role instance.
1576
1681
var r rbacv1.Role
1577
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & r )
1682
+ err := json .Unmarshal ([]byte (manifest ), & r )
1578
1683
if err != nil {
1579
1684
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1580
1685
}
@@ -1597,7 +1702,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1597
1702
case roleBindingKind :
1598
1703
// Marshal the manifest into a RoleBinding instance.
1599
1704
var rb rbacv1.RoleBinding
1600
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & rb )
1705
+ err := json .Unmarshal ([]byte (manifest ), & rb )
1601
1706
if err != nil {
1602
1707
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1603
1708
}
@@ -1620,7 +1725,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1620
1725
case serviceAccountKind :
1621
1726
// Marshal the manifest into a ServiceAccount instance.
1622
1727
var sa corev1.ServiceAccount
1623
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & sa )
1728
+ err := json .Unmarshal ([]byte (manifest ), & sa )
1624
1729
if err != nil {
1625
1730
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1626
1731
}
@@ -1643,7 +1748,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1643
1748
case serviceKind :
1644
1749
// Marshal the manifest into a Service instance
1645
1750
var s corev1.Service
1646
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & s )
1751
+ err := json .Unmarshal ([]byte (manifest ), & s )
1647
1752
if err != nil {
1648
1753
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1649
1754
}
@@ -1673,7 +1778,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1673
1778
1674
1779
case configMapKind :
1675
1780
var cfg corev1.ConfigMap
1676
- err := json .Unmarshal ([]byte (step . Resource . Manifest ), & cfg )
1781
+ err := json .Unmarshal ([]byte (manifest ), & cfg )
1677
1782
if err != nil {
1678
1783
return errorwrap .Wrapf (err , "error parsing step manifest: %s" , step .Resource .Name )
1679
1784
}
@@ -1709,7 +1814,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1709
1814
}
1710
1815
1711
1816
// Marshal the manifest into an unstructured object
1712
- dec := yaml .NewYAMLOrJSONDecoder (strings .NewReader (step . Resource . Manifest ), 10 )
1817
+ dec := yaml .NewYAMLOrJSONDecoder (strings .NewReader (manifest ), 10 )
1713
1818
unstructuredObject := & unstructured.Unstructured {}
1714
1819
if err := dec .Decode (unstructuredObject ); err != nil {
1715
1820
return errorwrap .Wrapf (err , "error decoding %s object to an unstructured object" , step .Resource .Name )
0 commit comments