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