@@ -1021,6 +1021,44 @@ func (o *Operator) ResolvePlan(plan *v1alpha1.InstallPlan) error {
1021
1021
return nil
1022
1022
}
1023
1023
1024
+ // TODO: in the future this will be extended to verify more than just whether or not the schema changed
1025
+ func checkCRDSchemas (oldCRD * v1beta1ext.CustomResourceDefinition , newCRD * v1beta1ext.CustomResourceDefinition ) bool {
1026
+ if reflect .DeepEqual (oldCRD .Spec .Validation , newCRD .Spec .Validation ) {
1027
+ return true
1028
+ }
1029
+
1030
+ return false
1031
+ }
1032
+
1033
+ func safeToUpdate (oldCRD * v1beta1ext.CustomResourceDefinition , newCRD * v1beta1ext.CustomResourceDefinition ) error {
1034
+ shouldCheckSchema := len (oldCRD .Spec .Versions ) == len (newCRD .Spec .Versions ) // no version bump
1035
+
1036
+ // 1) if there's no version change, verify that schemas match 2) ensure all old versions are present
1037
+ for _ , oldVersion := range oldCRD .Spec .Versions {
1038
+ var versionPresent bool
1039
+ for _ , newVersion := range newCRD .Spec .Versions {
1040
+ if oldVersion .Name == newVersion .Name {
1041
+ if shouldCheckSchema && ! checkCRDSchemas (oldCRD , newCRD ) {
1042
+ return fmt .Errorf ("not allowing CRD (%v) update with multiple owners with schema change on version %v" , newCRD .GetName (), oldVersion )
1043
+ }
1044
+ versionPresent = true
1045
+ }
1046
+ }
1047
+ if ! versionPresent {
1048
+ return fmt .Errorf ("not allowing CRD (%v) update with unincluded version %v" , newCRD .GetName (), oldVersion )
1049
+ }
1050
+ }
1051
+
1052
+ // ensure a CRD with multiple versions isn't checked
1053
+ if newCRD .Spec .Version != "" {
1054
+ if ! checkCRDSchemas (oldCRD , newCRD ) {
1055
+ return fmt .Errorf ("not allowing CRD (%v) update with multiple owners with schema change on (single) version %v" , newCRD .GetName (), newCRD .Spec .Version )
1056
+ }
1057
+ }
1058
+ return nil
1059
+
1060
+ }
1061
+
1024
1062
// ExecutePlan applies a planned InstallPlan to a namespace.
1025
1063
func (o * Operator ) ExecutePlan (plan * v1alpha1.InstallPlan ) error {
1026
1064
if plan .Status .Phase != v1alpha1 .InstallPlanPhaseInstalling {
@@ -1067,9 +1105,19 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
1067
1105
if err != nil {
1068
1106
return errorwrap .Wrapf (err , "error find matched CSV: %s" , step .Resource .Name )
1069
1107
}
1108
+ crd .SetResourceVersion (currentCRD .GetResourceVersion ())
1070
1109
if len (matchedCSV ) == 1 {
1071
- // Attempt to update CRD
1072
- crd .SetResourceVersion (currentCRD .GetResourceVersion ())
1110
+ o .logger .Debugf ("Found one owner for CRD %v" , crd )
1111
+ _ , err = o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().Update (& crd )
1112
+ if err != nil {
1113
+ return errorwrap .Wrapf (err , "error updating CRD: %s" , step .Resource .Name )
1114
+ }
1115
+ } else if len (matchedCSV ) > 1 {
1116
+ o .logger .Debugf ("Found multiple owners for CRD %v" , crd )
1117
+ if err := safeToUpdate (currentCRD , & crd ); err != nil {
1118
+ return err
1119
+ }
1120
+
1073
1121
_ , err = o .opClient .ApiextensionsV1beta1Interface ().ApiextensionsV1beta1 ().CustomResourceDefinitions ().Update (& crd )
1074
1122
if err != nil {
1075
1123
return errorwrap .Wrapf (err , "error update CRD: %s" , step .Resource .Name )
0 commit comments