@@ -147,11 +147,13 @@ type PrunerOptions struct {
147
147
// Images is the entire list of images in OpenShift. An image must be in this
148
148
// list to be a candidate for pruning.
149
149
Images * imageapi.ImageList
150
+ // ImageWatcher watches for image changes.
151
+ ImageWatcher watch.Interface
150
152
// Streams is the entire list of image streams across all namespaces in the
151
153
// cluster.
152
154
Streams * imageapi.ImageStreamList
153
- // StreamsWatcher watches for stream changes.
154
- StreamsWatcher watch.Interface
155
+ // StreamWatcher watches for stream changes.
156
+ StreamWatcher watch.Interface
155
157
// Pods is the entire list of pods across all namespaces in the cluster.
156
158
Pods * kapi.PodList
157
159
// RCs is the entire list of replication controllers across all namespaces in
@@ -205,6 +207,7 @@ type pruner struct {
205
207
algorithm pruneAlgorithm
206
208
registryClientFactory RegistryClientFactoryFunc
207
209
registryURL * url.URL
210
+ imageWatcher watch.Interface
208
211
imageStreamWatcher watch.Interface
209
212
imageStreamLimits map [string ][]* kapi.LimitRange
210
213
// sorted queue of images to prune
@@ -292,7 +295,8 @@ func NewPruner(options PrunerOptions) (Pruner, kerrors.Aggregate) {
292
295
registryClientFactory : options .RegistryClientFactory ,
293
296
registryURL : options .RegistryURL ,
294
297
processedImages : make (map [* imagegraph.ImageNode ]* Job ),
295
- imageStreamWatcher : options .StreamsWatcher ,
298
+ imageWatcher : options .ImageWatcher ,
299
+ imageStreamWatcher : options .StreamWatcher ,
296
300
imageStreamLimits : options .LimitRanges ,
297
301
numWorkers : options .NumWorkers ,
298
302
}
@@ -828,14 +832,52 @@ func (p *pruner) handleImageStreamEvent(event watch.Event) {
828
832
if isNode != nil {
829
833
glog .V (4 ).Infof ("Removing updated ImageStream %s from the graph" , getName (is ))
830
834
// first remove the current node if present
831
- p .g .RemoveNode (imagegraph . EnsureImageStreamNode ( p . g , is ) )
835
+ p .g .RemoveNode (isNode )
832
836
}
833
837
834
838
glog .V (4 ).Infof ("Adding updated ImageStream %s back to the graph" , getName (is ))
835
839
p .addImageStreamsToGraph (& imageapi.ImageStreamList {Items : []imageapi.ImageStream {* is }}, p .imageStreamLimits )
836
840
}
837
841
}
838
842
843
+ func (p * pruner ) handleImageEvent (event watch.Event ) {
844
+ getImageNode := func () (* imageapi.Image , * imagegraph.ImageNode ) {
845
+ img , ok := event .Object .(* imageapi.Image )
846
+ if ! ok {
847
+ utilruntime .HandleError (fmt .Errorf ("internal error: expected Image object in %s event, not %T" , event .Type , event .Object ))
848
+ return nil , nil
849
+ }
850
+ n := p .g .Find (imagegraph .ImageNodeName (img ))
851
+ if imgNode , ok := n .(* imagegraph.ImageNode ); ok {
852
+ return img , imgNode
853
+ }
854
+ return img , nil
855
+ }
856
+
857
+ switch event .Type {
858
+ case watch .Added :
859
+ img , imgNode := getImageNode ()
860
+ if img == nil {
861
+ return
862
+ }
863
+ if imgNode != nil {
864
+ glog .V (4 ).Infof ("Ignoring added Image %s that is already present in the graph" , img )
865
+ return
866
+ }
867
+ glog .V (4 ).Infof ("Adding new Image %s to the graph" , img .Name )
868
+ p .addImagesToGraph (& imageapi.ImageList {Items : []imageapi.Image {* img }})
869
+
870
+ case watch .Deleted :
871
+ img , imgNode := getImageNode ()
872
+ if imgNode == nil {
873
+ glog .V (4 ).Infof ("Ignoring event for deleted Image %s that is not present in the graph" , img .Name )
874
+ return
875
+ }
876
+ glog .V (4 ).Infof ("Removing deleted image %s from the graph" , img .Name )
877
+ p .g .RemoveNode (imgNode )
878
+ }
879
+ }
880
+
839
881
// getImageNodes returns only nodes of type ImageNode.
840
882
func getImageNodes (nodes []gonum.Node ) map [string ]* imagegraph.ImageNode {
841
883
ret := make (map [string ]* imagegraph.ImageNode )
@@ -1205,6 +1247,7 @@ func (p *pruner) runLoop(
1205
1247
jobChan chan <- * Job ,
1206
1248
resultChan <- chan JobResult ,
1207
1249
) (deletions []Deletion , failures []Failure ) {
1250
+ imgUpdateChan := p .imageWatcher .ResultChan ()
1208
1251
isUpdateChan := p .imageStreamWatcher .ResultChan ()
1209
1252
for {
1210
1253
// make workers busy
@@ -1235,7 +1278,8 @@ func (p *pruner) runLoop(
1235
1278
delete (p .processedImages , res .Job .Image )
1236
1279
case event := <- isUpdateChan :
1237
1280
p .handleImageStreamEvent (event )
1238
- // TODO: handle new images - do not add them to the queue though
1281
+ case event := <- imgUpdateChan :
1282
+ p .handleImageEvent (event )
1239
1283
}
1240
1284
}
1241
1285
}
0 commit comments