@@ -1127,17 +1127,23 @@ func (o *Operator) ResolvePlan(plan *v1alpha1.InstallPlan) error {
1127
1127
return nil
1128
1128
}
1129
1129
1130
- // Ensure all existing served versions are present in new CRD
1131
- func ensureCRDVersions (oldCRD * v1beta1ext.CustomResourceDefinition , newCRD * v1beta1ext.CustomResourceDefinition ) error {
1132
- newCRDVersions := map [string ]struct {}{}
1130
+ func getCRDVersionsMap (crd * v1beta1ext.CustomResourceDefinition ) map [string ]struct {} {
1131
+ versionsMap := map [string ]struct {}{}
1133
1132
1134
- for _ , newVersion := range newCRD .Spec .Versions {
1135
- newCRDVersions [ newVersion .Name ] = struct {}{}
1133
+ for _ , version := range crd .Spec .Versions {
1134
+ versionsMap [ version .Name ] = struct {}{}
1136
1135
}
1137
- if newCRD .Spec .Version != "" {
1138
- newCRDVersions [ newCRD .Spec .Version ] = struct {}{}
1136
+ if crd .Spec .Version != "" {
1137
+ versionsMap [ crd .Spec .Version ] = struct {}{}
1139
1138
}
1140
1139
1140
+ return versionsMap
1141
+ }
1142
+
1143
+ // Ensure all existing served versions are present in new CRD
1144
+ func ensureCRDVersions (oldCRD * v1beta1ext.CustomResourceDefinition , newCRD * v1beta1ext.CustomResourceDefinition ) error {
1145
+ newCRDVersions := getCRDVersionsMap (newCRD )
1146
+
1141
1147
for _ , oldVersion := range oldCRD .Spec .Versions {
1142
1148
if oldVersion .Served {
1143
1149
_ , ok := newCRDVersions [oldVersion .Name ]
@@ -1202,10 +1208,36 @@ func (o *Operator) validateExistingCRs(gvr schema.GroupVersionResource, newCRD *
1202
1208
return fmt .Errorf ("error validating custom resource against new schema %#v: %s" , newCRD .Spec .Validation , err )
1203
1209
}
1204
1210
}
1205
-
1206
1211
return nil
1207
1212
}
1208
1213
1214
+ // Attempt to remove stored versions that have been deprecated before allowing
1215
+ // those versions to be removed from the new CRD.
1216
+ // The function may not always succeed as storedVersions requires at least one
1217
+ // version. If there is only stored version, it won't be removed until a new
1218
+ // stored version is added.
1219
+ func removeDeprecatedStoredVersions (oldCRD * v1beta1ext.CustomResourceDefinition , newCRD * v1beta1ext.CustomResourceDefinition ) []string {
1220
+ // StoredVersions requires to have at least one version.
1221
+ if len (oldCRD .Status .StoredVersions ) <= 1 {
1222
+ return nil
1223
+ }
1224
+
1225
+ newStoredVersions := []string {}
1226
+ newCRDVersions := getCRDVersionsMap (newCRD )
1227
+ for _ , v := range oldCRD .Status .StoredVersions {
1228
+ _ , ok := newCRDVersions [v ]
1229
+ if ok {
1230
+ newStoredVersions = append (newStoredVersions , v )
1231
+ }
1232
+ }
1233
+
1234
+ if len (newStoredVersions ) < 1 {
1235
+ return nil
1236
+ } else {
1237
+ return newStoredVersions
1238
+ }
1239
+ }
1240
+
1209
1241
// ExecutePlan applies a planned InstallPlan to a namespace.
1210
1242
func (o * Operator ) ExecutePlan (plan * v1alpha1.InstallPlan ) error {
1211
1243
if plan .Status .Phase != v1alpha1 .InstallPlanPhaseInstalling {
@@ -1255,7 +1287,9 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1255
1287
if k8serrors .IsAlreadyExists (err ) {
1256
1288
currentCRD , _ := o .lister .APIExtensionsV1beta1 ().CustomResourceDefinitionLister ().Get (crd .GetName ())
1257
1289
// Compare 2 CRDs to see if it needs to be updatetd
1258
- if ! reflect .DeepEqual (crd , * currentCRD ) {
1290
+ if ! (reflect .DeepEqual (crd .Spec .Version , currentCRD .Spec .Version ) &&
1291
+ reflect .DeepEqual (crd .Spec .Versions , currentCRD .Spec .Versions ) &&
1292
+ reflect .DeepEqual (crd .Spec .Validation , currentCRD .Spec .Validation )) {
1259
1293
// Verify CRD ownership, only attempt to update if
1260
1294
// CRD has only one owner
1261
1295
// Example: provided=database.coreos.com/v1alpha1/EtcdCluster
@@ -1266,11 +1300,6 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1266
1300
crd .SetResourceVersion (currentCRD .GetResourceVersion ())
1267
1301
if len (matchedCSV ) == 1 {
1268
1302
o .logger .Debugf ("Found one owner for CRD %v" , crd )
1269
-
1270
- _ , err = o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().Update (& crd )
1271
- if err != nil {
1272
- return errorwrap .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
1273
- }
1274
1303
} else if len (matchedCSV ) > 1 {
1275
1304
o .logger .Debugf ("Found multiple owners for CRD %v" , crd )
1276
1305
@@ -1282,11 +1311,21 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1282
1311
if err = o .validateCustomResourceDefinition (currentCRD , & crd ); err != nil {
1283
1312
return errorwrap .Wrapf (err , "error validating existing CRs agains new CRD's schema: %s" , step .Resource .Name )
1284
1313
}
1285
-
1286
- _ , err = o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().Update (& crd )
1314
+ }
1315
+ // Remove deprecated version in CRD storedVersions
1316
+ storeVersions := removeDeprecatedStoredVersions (currentCRD , & crd )
1317
+ if storeVersions != nil {
1318
+ currentCRD .Status .StoredVersions = storeVersions
1319
+ resultCRD , err := o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().UpdateStatus (currentCRD )
1287
1320
if err != nil {
1288
- return errorwrap .Wrapf (err , "error update CRD: %s" , step .Resource .Name )
1321
+ return errorwrap .Wrapf (err , "error updating CRD's status : %s" , step .Resource .Name )
1289
1322
}
1323
+ crd .SetResourceVersion (resultCRD .GetResourceVersion ())
1324
+ }
1325
+ // Update CRD to new version
1326
+ _ , err = o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().Update (& crd )
1327
+ if err != nil {
1328
+ return errorwrap .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
1290
1329
}
1291
1330
}
1292
1331
// If it already existed, mark the step as Present.
0 commit comments