@@ -66,6 +66,109 @@ func TestSolveOperators(t *testing.T) {
66
66
require .EqualValues (t , expected , operators )
67
67
}
68
68
69
+ func TestSolveOperators_WithSystemConstraints (t * testing.T ) {
70
+ const namespace = "test-namespace"
71
+ catalog := cache.SourceKey {Name : "test-catalog" , Namespace : namespace }
72
+
73
+ packageASub := newSub (namespace , "packageA" , "alpha" , catalog )
74
+ packageDSub := existingSub (namespace , "packageD.v1" , "packageD" , "alpha" , catalog )
75
+
76
+ APISet := cache.APISet {opregistry.APIKey {Group : "g" , Version : "v" , Kind : "k" , Plural : "ks" }: struct {}{}}
77
+
78
+ // packageA requires an API that can be provided by B or C
79
+ packageA := genOperator ("packageA.v1" , "0.0.1" , "" , "packageA" , "alpha" , catalog .Name , catalog .Namespace , APISet , nil , nil , "" , false )
80
+ packageB := genOperator ("packageB.v1" , "1.0.0" , "" , "packageB" , "alpha" , catalog .Name , catalog .Namespace , nil , APISet , nil , "" , false )
81
+ packageC := genOperator ("packageC.v1" , "1.0.0" , "" , "packageC" , "alpha" , catalog .Name , catalog .Namespace , nil , APISet , nil , "" , false )
82
+
83
+ // Existing operators
84
+ packageD := genOperator ("packageD.v1" , "1.0.0" , "" , "packageD" , "alpha" , catalog .Name , catalog .Namespace , nil , nil , nil , "" , false )
85
+ existingPackageD := existingOperator (namespace , "packageD.v1" , "packageD" , "alpha" , "" , nil , nil , nil , nil )
86
+ existingPackageD .Annotations = map [string ]string {"operatorframework.io/properties" : `{"properties":[{"type":"olm.package","value":{"packageName":"packageD","version":"1.0.0"}}]}` }
87
+
88
+ whiteListConstraintProvider := func (whiteList ... * cache.Entry ) solver.ConstraintProviderFunc {
89
+ return func (entry * cache.Entry ) ([]solver.Constraint , error ) {
90
+ for _ , whiteListedEntry := range whiteList {
91
+ if whiteListedEntry .Package () == entry .Package () &&
92
+ whiteListedEntry .Name == entry .Name &&
93
+ whiteListedEntry .Version == entry .Version {
94
+ return nil , nil
95
+ }
96
+ }
97
+ return []solver.Constraint {PrettyConstraint (
98
+ solver .Prohibited (),
99
+ fmt .Sprintf ("package: %s is not white listed" , entry .Package ()),
100
+ )}, nil
101
+ }
102
+ }
103
+
104
+ testCases := []struct {
105
+ title string
106
+ systemConstraintsProvider solver.ConstraintProvider
107
+ expectedOperators cache.OperatorSet
108
+ csvs []* v1alpha1.ClusterServiceVersion
109
+ subs []* v1alpha1.Subscription
110
+ snapshotEntries []* cache.Entry
111
+ err string
112
+ }{
113
+ {
114
+ title : "No runtime constraints" ,
115
+ snapshotEntries : []* cache.Entry {packageA , packageB , packageC , packageD },
116
+ systemConstraintsProvider : nil ,
117
+ expectedOperators : cache.OperatorSet {"packageA.v1" : packageA , "packageB.v1" : packageB },
118
+ csvs : nil ,
119
+ subs : []* v1alpha1.Subscription {packageASub },
120
+ err : "" ,
121
+ },
122
+ {
123
+ title : "Runtime constraints only accept packages A and C" ,
124
+ snapshotEntries : []* cache.Entry {packageA , packageB , packageC , packageD },
125
+ systemConstraintsProvider : whiteListConstraintProvider (packageA , packageC ),
126
+ expectedOperators : cache.OperatorSet {"packageA.v1" : packageA , "packageC.v1" : packageC },
127
+ csvs : nil ,
128
+ subs : []* v1alpha1.Subscription {packageASub },
129
+ err : "" ,
130
+ },
131
+ {
132
+ title : "Existing packages are ignored" ,
133
+ snapshotEntries : []* cache.Entry {packageA , packageB , packageC , packageD },
134
+ systemConstraintsProvider : whiteListConstraintProvider (packageA , packageC ),
135
+ expectedOperators : cache.OperatorSet {"packageA.v1" : packageA , "packageC.v1" : packageC },
136
+ csvs : []* v1alpha1.ClusterServiceVersion {existingPackageD },
137
+ subs : []* v1alpha1.Subscription {packageASub , packageDSub },
138
+ err : "" ,
139
+ },
140
+ {
141
+ title : "Runtime constraints don't allow A" ,
142
+ snapshotEntries : []* cache.Entry {packageA , packageB , packageC , packageD },
143
+ systemConstraintsProvider : whiteListConstraintProvider (),
144
+ expectedOperators : nil ,
145
+ csvs : nil ,
146
+ subs : []* v1alpha1.Subscription {packageASub },
147
+ err : "packageA is not white listed" ,
148
+ },
149
+ }
150
+
151
+ for _ , testCase := range testCases {
152
+ satResolver := SatResolver {
153
+ cache : cache .New (cache.StaticSourceProvider {
154
+ catalog : & cache.Snapshot {
155
+ Entries : testCase .snapshotEntries ,
156
+ },
157
+ }),
158
+ log : logrus .New (),
159
+ systemConstraintsProvider : testCase .systemConstraintsProvider ,
160
+ }
161
+ operators , err := satResolver .SolveOperators ([]string {namespace }, testCase .csvs , testCase .subs )
162
+
163
+ if testCase .err != "" {
164
+ require .Containsf (t , err .Error (), testCase .err , "Test %s failed" , testCase .title )
165
+ } else {
166
+ require .NoErrorf (t , err , "Test %s failed" , testCase .title )
167
+ }
168
+ require .EqualValuesf (t , testCase .expectedOperators , operators , "Test %s failed" , testCase .title )
169
+ }
170
+ }
171
+
69
172
func TestDisjointChannelGraph (t * testing.T ) {
70
173
const namespace = "test-namespace"
71
174
catalog := cache.SourceKey {Name : "test-catalog" , Namespace : namespace }
0 commit comments