@@ -17,6 +17,7 @@ import (
17
17
rbacv1 "k8s.io/api/rbac/v1"
18
18
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
19
19
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
20
+ apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
20
21
"k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
21
22
extinf "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
22
23
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -1315,7 +1316,21 @@ func GetCRDV1VersionsMap(crd *apiextensionsv1.CustomResourceDefinition) map[stri
1315
1316
}
1316
1317
1317
1318
// Ensure all existing served versions are present in new CRD
1318
- func EnsureCRDVersions (oldCRD * apiextensionsv1.CustomResourceDefinition , newCRD * apiextensionsv1.CustomResourceDefinition ) error {
1319
+ func GetCRDV1Beta1VersionsMap (crd * apiextensionsv1beta1.CustomResourceDefinition ) map [string ]struct {} {
1320
+ versionsMap := map [string ]struct {}{}
1321
+
1322
+ for _ , version := range crd .Spec .Versions {
1323
+ versionsMap [version .Name ] = struct {}{}
1324
+ }
1325
+ if crd .Spec .Version != "" {
1326
+ versionsMap [crd .Spec .Version ] = struct {}{}
1327
+ }
1328
+
1329
+ return versionsMap
1330
+ }
1331
+
1332
+ // Ensure all existing served versions are present in new CRD
1333
+ func EnsureV1CRDVersions (oldCRD * apiextensionsv1.CustomResourceDefinition , newCRD * apiextensionsv1.CustomResourceDefinition ) error {
1319
1334
newCRDVersions := GetCRDV1VersionsMap (newCRD )
1320
1335
1321
1336
for _ , oldVersion := range oldCRD .Spec .Versions {
@@ -1329,6 +1344,27 @@ func EnsureCRDVersions(oldCRD *apiextensionsv1.CustomResourceDefinition, newCRD
1329
1344
return nil
1330
1345
}
1331
1346
1347
+ // Ensure all existing served versions are present in new CRD
1348
+ func EnsureV1Beta1CRDVersions (oldCRD * apiextensionsv1beta1.CustomResourceDefinition , newCRD * apiextensionsv1beta1.CustomResourceDefinition ) error {
1349
+ newCRDVersions := GetCRDV1Beta1VersionsMap (newCRD )
1350
+
1351
+ for _ , oldVersion := range oldCRD .Spec .Versions {
1352
+ if oldVersion .Served {
1353
+ _ , ok := newCRDVersions [oldVersion .Name ]
1354
+ if ! ok {
1355
+ return fmt .Errorf ("New CRD (%s) must contain existing served versions (%s)" , oldCRD .Name , oldVersion .Name )
1356
+ }
1357
+ }
1358
+ }
1359
+ if oldCRD .Spec .Version != "" {
1360
+ _ , ok := newCRDVersions [oldCRD .Spec .Version ]
1361
+ if ! ok {
1362
+ return fmt .Errorf ("New CRD (%s) must contain existing version (%s)" , oldCRD .Name , oldCRD .Spec .Version )
1363
+ }
1364
+ }
1365
+ return nil
1366
+ }
1367
+
1332
1368
// Validate all existing served versions against new CRD's validation (if changed)
1333
1369
func validateV1CRDCompatibility (dynamicClient dynamic.Interface , oldCRD * apiextensionsv1.CustomResourceDefinition , newCRD * apiextensionsv1.CustomResourceDefinition ) error {
1334
1370
logrus .Debugf ("Comparing %#v to %#v" , oldCRD .Spec .Versions , newCRD .Spec .Versions )
@@ -1364,6 +1400,38 @@ func validateV1CRDCompatibility(dynamicClient dynamic.Interface, oldCRD *apiexte
1364
1400
return nil
1365
1401
}
1366
1402
1403
+ // Validate all existing served versions against new CRD's validation (if changed)
1404
+ func validateV1Beta1CRDCompatibility (dynamicClient dynamic.Interface , oldCRD * apiextensionsv1beta1.CustomResourceDefinition , newCRD * apiextensionsv1beta1.CustomResourceDefinition ) error {
1405
+ logrus .Debugf ("Comparing %#v to %#v" , oldCRD .Spec .Validation , newCRD .Spec .Validation )
1406
+ // If validation schema is unchanged, return right away
1407
+ if reflect .DeepEqual (oldCRD .Spec .Validation , newCRD .Spec .Validation ) {
1408
+ return nil
1409
+ }
1410
+ convertedCRD := & apiextensions.CustomResourceDefinition {}
1411
+ if err := apiextensionsv1beta1 .Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition (newCRD , convertedCRD , nil ); err != nil {
1412
+ return err
1413
+ }
1414
+ for _ , version := range oldCRD .Spec .Versions {
1415
+ if ! version .Served {
1416
+ gvr := schema.GroupVersionResource {Group : oldCRD .Spec .Group , Version : version .Name , Resource : oldCRD .Spec .Names .Plural }
1417
+ err := validateExistingCRs (dynamicClient , gvr , convertedCRD )
1418
+ if err != nil {
1419
+ return err
1420
+ }
1421
+ }
1422
+ }
1423
+
1424
+ if oldCRD .Spec .Version != "" {
1425
+ gvr := schema.GroupVersionResource {Group : oldCRD .Spec .Group , Version : oldCRD .Spec .Version , Resource : oldCRD .Spec .Names .Plural }
1426
+ err := validateExistingCRs (dynamicClient , gvr , convertedCRD )
1427
+ if err != nil {
1428
+ return err
1429
+ }
1430
+ }
1431
+ logrus .Debugf ("Successfully validated CRD %s\n " , newCRD .Name )
1432
+ return nil
1433
+ }
1434
+
1367
1435
func validateExistingCRs (dynamicClient dynamic.Interface , gvr schema.GroupVersionResource , newCRD * apiextensions.CustomResourceDefinition ) error {
1368
1436
// make dynamic client
1369
1437
crList , err := dynamicClient .Resource (gvr ).List (context .TODO (), metav1.ListOptions {})
@@ -1410,6 +1478,28 @@ func removeDeprecatedV1StoredVersions(oldCRD *apiextensionsv1.CustomResourceDefi
1410
1478
}
1411
1479
}
1412
1480
1481
+ func removeDeprecatedV1Beta1StoredVersions (oldCRD * apiextensionsv1beta1.CustomResourceDefinition , newCRD * apiextensionsv1beta1.CustomResourceDefinition ) []string {
1482
+ // StoredVersions requires to have at least one version.
1483
+ if len (oldCRD .Status .StoredVersions ) <= 1 {
1484
+ return nil
1485
+ }
1486
+
1487
+ newStoredVersions := []string {}
1488
+ newCRDVersions := GetCRDV1Beta1VersionsMap (newCRD )
1489
+ for _ , v := range oldCRD .Status .StoredVersions {
1490
+ _ , ok := newCRDVersions [v ]
1491
+ if ok {
1492
+ newStoredVersions = append (newStoredVersions , v )
1493
+ }
1494
+ }
1495
+
1496
+ if len (newStoredVersions ) < 1 {
1497
+ return nil
1498
+ } else {
1499
+ return newStoredVersions
1500
+ }
1501
+ }
1502
+
1413
1503
// ExecutePlan applies a planned InstallPlan to a namespace.
1414
1504
func (o * Operator ) ExecutePlan (plan * v1alpha1.InstallPlan ) error {
1415
1505
if plan .Status .Phase != v1alpha1 .InstallPlanPhaseInstalling {
@@ -1436,7 +1526,7 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1436
1526
}
1437
1527
1438
1528
ensurer := newStepEnsurer (kubeclient , crclient , dynamicClient )
1439
- b := newBuilder (kubeclient , dynamicClient , o .csvProvidedAPIsIndexer )
1529
+ b := newBuilder (kubeclient , dynamicClient , o .csvProvidedAPIsIndexer , o . logger )
1440
1530
1441
1531
for i , step := range plan .Status .Plan {
1442
1532
doStep := true
0 commit comments