@@ -126,8 +126,9 @@ type BuildController struct {
126
126
podClient kexternalcoreclient.PodsGetter
127
127
kubeClient kclientset.Interface
128
128
129
- queue workqueue.RateLimitingInterface
129
+ buildQueue workqueue.RateLimitingInterface
130
130
imageStreamQueue * resourceTriggerQueue
131
+ buildConfigQueue workqueue.RateLimitingInterface
131
132
132
133
buildStore buildlister.BuildLister
133
134
secretStore v1lister.SecretLister
@@ -175,7 +176,6 @@ func NewBuildController(params *BuildControllerParams) *BuildController {
175
176
176
177
buildClient := buildclient .NewOSClientBuildClient (params .OpenshiftClient )
177
178
buildLister := params .BuildInformer .Lister ()
178
- clientBuildLister := buildclient .NewOSClientBuildLister (params .OpenshiftClient )
179
179
buildConfigGetter := params .BuildConfigInformer .Lister ()
180
180
c := & BuildController {
181
181
buildPatcher : buildClient ,
@@ -198,11 +198,12 @@ func NewBuildController(params *BuildControllerParams) *BuildController {
198
198
buildDefaults : params .BuildDefaults ,
199
199
buildOverrides : params .BuildOverrides ,
200
200
201
- queue : workqueue .NewRateLimitingQueue (workqueue .DefaultControllerRateLimiter ()),
201
+ buildQueue : workqueue .NewRateLimitingQueue (workqueue .DefaultControllerRateLimiter ()),
202
202
imageStreamQueue : newResourceTriggerQueue (),
203
+ buildConfigQueue : workqueue .NewRateLimitingQueue (workqueue .DefaultControllerRateLimiter ()),
203
204
204
205
recorder : eventBroadcaster .NewRecorder (kapi .Scheme , clientv1.EventSource {Component : "build-controller" }),
205
- runPolicies : policy .GetAllRunPolicies (clientBuildLister , buildClient ),
206
+ runPolicies : policy .GetAllRunPolicies (buildLister , buildClient ),
206
207
}
207
208
208
209
c .podInformer .AddEventHandler (cache.ResourceEventHandlerFuncs {
@@ -229,7 +230,8 @@ func NewBuildController(params *BuildControllerParams) *BuildController {
229
230
// Run begins watching and syncing.
230
231
func (bc * BuildController ) Run (workers int , stopCh <- chan struct {}) {
231
232
defer utilruntime .HandleCrash ()
232
- defer bc .queue .ShutDown ()
233
+ defer bc .buildQueue .ShutDown ()
234
+ defer bc .buildConfigQueue .ShutDown ()
233
235
234
236
// Wait for the controller stores to sync before starting any work in this controller.
235
237
if ! cache .WaitForCacheSync (stopCh , bc .buildStoreSynced , bc .podStoreSynced , bc .secretStoreSynced , bc .imageStreamStoreSynced ) {
@@ -240,7 +242,11 @@ func (bc *BuildController) Run(workers int, stopCh <-chan struct{}) {
240
242
glog .Infof ("Starting build controller" )
241
243
242
244
for i := 0 ; i < workers ; i ++ {
243
- go wait .Until (bc .worker , time .Second , stopCh )
245
+ go wait .Until (bc .buildWorker , time .Second , stopCh )
246
+ }
247
+
248
+ for i := 0 ; i < workers ; i ++ {
249
+ go wait .Until (bc .buildConfigWorker , time .Second , stopCh )
244
250
}
245
251
246
252
metrics .IntializeMetricsCollector (bc .buildLister )
@@ -249,38 +255,72 @@ func (bc *BuildController) Run(workers int, stopCh <-chan struct{}) {
249
255
glog .Infof ("Shutting down build controller" )
250
256
}
251
257
252
- func (bc * BuildController ) worker () {
258
+ func (bc * BuildController ) buildWorker () {
253
259
for {
254
- if quit := bc .work (); quit {
260
+ if quit := bc .buildWork (); quit {
255
261
return
256
262
}
257
263
}
258
264
}
259
265
260
- // work gets the next build from the queue and invokes handleBuild on it
261
- func (bc * BuildController ) work () bool {
262
- key , quit := bc .queue .Get ()
266
+ // buildWork gets the next build from the buildQueue and invokes handleBuild on it
267
+ func (bc * BuildController ) buildWork () bool {
268
+ key , quit := bc .buildQueue .Get ()
263
269
if quit {
264
270
return true
265
271
}
266
272
267
- defer bc .queue .Done (key )
273
+ defer bc .buildQueue .Done (key )
268
274
269
275
build , err := bc .getBuildByKey (key .(string ))
270
276
if err != nil {
271
- bc .handleError (err , key )
277
+ bc .handleBuildError (err , key )
272
278
return false
273
279
}
274
280
if build == nil {
275
281
return false
276
282
}
277
283
278
284
err = bc .handleBuild (build )
285
+ bc .handleBuildError (err , key )
286
+ return false
287
+ }
279
288
280
- bc .handleError (err , key )
289
+ func (bc * BuildController ) buildConfigWorker () {
290
+ for {
291
+ if quit := bc .buildConfigWork (); quit {
292
+ return
293
+ }
294
+ }
295
+ }
296
+
297
+ // buildConfigWork gets the next build config from the buildConfigQueue and invokes handleBuildConfig on it
298
+ func (bc * BuildController ) buildConfigWork () bool {
299
+ key , quit := bc .buildConfigQueue .Get ()
300
+ if quit {
301
+ return true
302
+ }
303
+ defer bc .buildConfigQueue .Done (key )
304
+
305
+ namespace , name , err := parseBuildConfigKey (key .(string ))
306
+ if err != nil {
307
+ utilruntime .HandleError (err )
308
+ return false
309
+ }
310
+
311
+ err = bc .handleBuildConfig (namespace , name )
312
+ bc .handleBuildConfigError (err , key )
281
313
return false
282
314
}
283
315
316
+ func parseBuildConfigKey (key string ) (string , string , error ) {
317
+ parts := strings .SplitN (key , "/" , 2 )
318
+ if len (parts ) != 2 {
319
+ return "" , "" , fmt .Errorf ("invalid build config key: %s" , key )
320
+ }
321
+ return parts [0 ], parts [1 ], nil
322
+ }
323
+
284
324
// handleBuild retrieves the build's corresponding pod and calls the appropriate
285
325
// handle function based on the build's current state. Each handler returns a buildUpdate
286
326
// object that includes any updates that need to be made on the build.
@@ -956,12 +996,46 @@ func (bc *BuildController) updateBuild(build *buildapi.Build, update *buildUpdat
956
996
bc .recorder .Eventf (patchedBuild , kapi .EventTypeNormal , buildapi .BuildFailedEventReason , fmt .Sprintf (buildapi .BuildFailedEventMessage , patchedBuild .Namespace , patchedBuild .Name ))
957
997
}
958
998
if buildutil .IsTerminalPhase (* update .phase ) {
959
- common . HandleBuildCompletion (patchedBuild , bc . buildLister , bc . buildConfigGetter , bc . buildDeleter , bc . runPolicies )
999
+ bc . handleBuildCompletion (patchedBuild )
960
1000
}
961
1001
}
962
1002
return nil
963
1003
}
964
1004
1005
+ func (bc * BuildController ) handleBuildCompletion (build * buildapi.Build ) {
1006
+ bcName := buildutil .ConfigNameForBuild (build )
1007
+ bc .enqueueBuildConfig (build .Namespace , bcName )
1008
+ if err := common .HandleBuildPruning (bcName , build .Namespace , bc .buildLister , bc .buildConfigGetter , bc .buildDeleter ); err != nil {
1009
+ utilruntime .HandleError (fmt .Errorf ("failed to prune old builds %s/%s: %v" , build .Namespace , build .Name , err ))
1010
+ }
1011
+ }
1012
+
1013
+ func (bc * BuildController ) enqueueBuildConfig (ns , name string ) {
1014
+ key := resourceName (ns , name )
1015
+ bc .buildConfigQueue .Add (key )
1016
+ }
1017
+
1018
+ func (bc * BuildController ) handleBuildConfig (bcNamespace string , bcName string ) error {
1019
+ glog .V (4 ).Infof ("Handing build config %s/%s" , bcNamespace , bcName )
1020
+ nextBuilds , hasRunningBuilds , err := policy .GetNextConfigBuild (bc .buildLister , bcNamespace , bcName )
1021
+ if err != nil {
1022
+ glog .V (2 ).Infof ("Error getting next builds for %s/%s: %v" , bcNamespace , bcName , err )
1023
+ return err
1024
+ }
1025
+ glog .V (5 ).Infof ("Build config %s/%s: has %d next builds, is running builds: %v" , bcNamespace , bcName , len (nextBuilds ), hasRunningBuilds )
1026
+ if len (nextBuilds ) == 0 && hasRunningBuilds {
1027
+ glog .V (4 ).Infof ("Build config %s/%s has running builds, will retry" , bcNamespace , bcName )
1028
+ return fmt .Errorf ("build config %s/%s has running builds and cannot run more builds" , bcNamespace , bcName )
1029
+ }
1030
+
1031
+ // Enqueue any builds to build next
1032
+ for _ , build := range nextBuilds {
1033
+ glog .V (5 ).Infof ("Queueing next build for build config %s/%s: %s" , bcNamespace , bcName , build .Name )
1034
+ bc .enqueueBuild (build )
1035
+ }
1036
+ return nil
1037
+ }
1038
+
965
1039
// patchBuild generates a patch for the given build and buildUpdate
966
1040
// and applies that patch using the REST client
967
1041
func (bc * BuildController ) patchBuild (build * buildapi.Build , update * buildUpdate ) (* buildapi.Build , error ) {
@@ -1059,16 +1133,16 @@ func (bc *BuildController) buildUpdated(old, cur interface{}) {
1059
1133
bc .enqueueBuild (build )
1060
1134
}
1061
1135
1062
- // enqueueBuild adds the given build to the queue .
1136
+ // enqueueBuild adds the given build to the buildQueue .
1063
1137
func (bc * BuildController ) enqueueBuild (build * buildapi.Build ) {
1064
1138
key := resourceName (build .Namespace , build .Name )
1065
- bc .queue .Add (key )
1139
+ bc .buildQueue .Add (key )
1066
1140
}
1067
1141
1068
1142
// enqueueBuildForPod adds the build corresponding to the given pod to the controller
1069
- // queue . If a build is not found for the pod, then an error is logged.
1143
+ // buildQueue . If a build is not found for the pod, then an error is logged.
1070
1144
func (bc * BuildController ) enqueueBuildForPod (pod * v1.Pod ) {
1071
- bc .queue .Add (resourceName (pod .Namespace , buildutil .GetBuildName (pod )))
1145
+ bc .buildQueue .Add (resourceName (pod .Namespace , buildutil .GetBuildName (pod )))
1072
1146
}
1073
1147
1074
1148
// imageStreamAdded queues any builds that have registered themselves for this image stream.
@@ -1077,7 +1151,7 @@ func (bc *BuildController) enqueueBuildForPod(pod *v1.Pod) {
1077
1151
func (bc * BuildController ) imageStreamAdded (obj interface {}) {
1078
1152
stream := obj .(* imageapi.ImageStream )
1079
1153
for _ , buildKey := range bc .imageStreamQueue .Pop (resourceName (stream .Namespace , stream .Name )) {
1080
- bc .queue .Add (buildKey )
1154
+ bc .buildQueue .Add (buildKey )
1081
1155
}
1082
1156
}
1083
1157
@@ -1086,29 +1160,48 @@ func (bc *BuildController) imageStreamUpdated(old, cur interface{}) {
1086
1160
bc .imageStreamAdded (cur )
1087
1161
}
1088
1162
1089
- // handleError is called by the main work loop to check the return of calling handleBuild.
1090
- // If an error occurred, then the key is re-added to the queue unless it has been retried too many
1163
+ // handleBuildError is called by the main work loop to check the return of calling handleBuild.
1164
+ // If an error occurred, then the key is re-added to the buildQueue unless it has been retried too many
1091
1165
// times.
1092
- func (bc * BuildController ) handleError (err error , key interface {}) {
1166
+ func (bc * BuildController ) handleBuildError (err error , key interface {}) {
1093
1167
if err == nil {
1094
- bc .queue .Forget (key )
1168
+ bc .buildQueue .Forget (key )
1095
1169
return
1096
1170
}
1097
1171
1098
1172
if strategy .IsFatal (err ) {
1099
1173
glog .V (2 ).Infof ("Will not retry fatal error for key %v: %v" , key , err )
1100
- bc .queue .Forget (key )
1174
+ bc .buildQueue .Forget (key )
1175
+ return
1176
+ }
1177
+
1178
+ if bc .buildQueue .NumRequeues (key ) < maxRetries {
1179
+ glog .V (4 ).Infof ("Retrying key %v: %v" , key , err )
1180
+ bc .buildQueue .AddRateLimited (key )
1181
+ return
1182
+ }
1183
+
1184
+ glog .V (2 ).Infof ("Giving up retrying %v: %v" , key , err )
1185
+ bc .buildQueue .Forget (key )
1186
+ }
1187
+
1188
+ // handleBuildConfigError is called by the buildConfig work loop to check the return of calling handleBuildConfig.
1189
+ // If an error occurred, then the key is re-added to the buildConfigQueue unless it has been retried too many
1190
+ // times.
1191
+ func (bc * BuildController ) handleBuildConfigError (err error , key interface {}) {
1192
+ if err == nil {
1193
+ bc .buildConfigQueue .Forget (key )
1101
1194
return
1102
1195
}
1103
1196
1104
- if bc .queue .NumRequeues (key ) < maxRetries {
1197
+ if bc .buildConfigQueue .NumRequeues (key ) < maxRetries {
1105
1198
glog .V (4 ).Infof ("Retrying key %v: %v" , key , err )
1106
- bc .queue .AddRateLimited (key )
1199
+ bc .buildConfigQueue .AddRateLimited (key )
1107
1200
return
1108
1201
}
1109
1202
1110
1203
glog .V (2 ).Infof ("Giving up retrying %v: %v" , key , err )
1111
- bc .queue .Forget (key )
1204
+ bc .buildConfigQueue .Forget (key )
1112
1205
}
1113
1206
1114
1207
// isBuildPod returns true if the given pod is a build pod
0 commit comments