@@ -20,6 +20,7 @@ import (
20
20
kerrors "k8s.io/apimachinery/pkg/util/errors"
21
21
"k8s.io/apimachinery/pkg/util/sets"
22
22
kapi "k8s.io/kubernetes/pkg/api"
23
+ "k8s.io/kubernetes/pkg/client/retry"
23
24
24
25
"github.com/openshift/origin/pkg/api/graph"
25
26
kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
@@ -71,9 +72,11 @@ type ImageDeleter interface {
71
72
72
73
// ImageStreamDeleter knows how to remove an image reference from an image stream.
73
74
type ImageStreamDeleter interface {
74
- // DeleteImageStream removes all references to the image from the image
75
+ // GetImageStream returns a fresh copy of an image stream.
76
+ GetImageStream (stream * imageapi.ImageStream ) (* imageapi.ImageStream , error )
77
+ // UpdateImageStream removes all references to the image from the image
75
78
// stream's status.tags. The updated image stream is returned.
76
- DeleteImageStream (stream * imageapi.ImageStream , image * imageapi.Image , updatedTags []string ) (* imageapi.ImageStream , error )
79
+ UpdateImageStream (stream * imageapi.ImageStream , image * imageapi.Image , updatedTags []string ) (* imageapi.ImageStream , error )
77
80
}
78
81
79
82
// BlobDeleter knows how to delete a blob from the Docker registry.
@@ -671,7 +674,7 @@ func calculatePrunableImageComponents(g graph.Graph) []*imagegraph.ImageComponen
671
674
}
672
675
673
676
// pruneStreams removes references from all image streams' status.tags entries
674
- // to prunable images, invoking streamPruner.DeleteImageStream for each updated
677
+ // to prunable images, invoking streamPruner.UpdateImageStream for each updated
675
678
// stream.
676
679
func pruneStreams (g graph.Graph , imageNodes []* imagegraph.ImageNode , streamPruner ImageStreamDeleter ) []error {
677
680
errs := []error {}
@@ -684,43 +687,49 @@ func pruneStreams(g graph.Graph, imageNodes []*imagegraph.ImageNode, streamPrune
684
687
continue
685
688
}
686
689
687
- stream := streamNode .ImageStream
688
- updatedTags := sets .NewString ()
690
+ if err := retry .RetryOnConflict (retry .DefaultRetry , func () error {
691
+ stream , err := streamPruner .GetImageStream (streamNode .ImageStream )
692
+ if err != nil {
693
+ return err
694
+ }
695
+ updatedTags := sets .NewString ()
689
696
690
- glog .V (4 ).Infof ("Checking if ImageStream %s has references to image %s in status.tags" , getName (stream ), imageNode .Image .Name )
697
+ glog .V (4 ).Infof ("Checking if ImageStream %s has references to image %s in status.tags" , getName (stream ), imageNode .Image .Name )
691
698
692
- for tag , history := range stream .Status .Tags {
693
- glog .V (4 ).Infof ("Checking tag %q" , tag )
699
+ for tag , history := range stream .Status .Tags {
700
+ glog .V (4 ).Infof ("Checking tag %q" , tag )
694
701
695
- newHistory := imageapi.TagEventList {}
702
+ newHistory := imageapi.TagEventList {}
696
703
697
- for i , tagEvent := range history .Items {
698
- glog .V (4 ).Infof ("Checking tag event %d with image %q" , i , tagEvent .Image )
704
+ for i , tagEvent := range history .Items {
705
+ glog .V (4 ).Infof ("Checking tag event %d with image %q" , i , tagEvent .Image )
699
706
700
- if tagEvent .Image != imageNode .Image .Name {
701
- glog .V (4 ).Infof ("Tag event doesn't match deleted image - keeping" )
702
- newHistory .Items = append (newHistory .Items , tagEvent )
707
+ if tagEvent .Image != imageNode .Image .Name {
708
+ glog .V (4 ).Infof ("Tag event doesn't match deleted image - keeping" )
709
+ newHistory .Items = append (newHistory .Items , tagEvent )
710
+ } else {
711
+ glog .V (4 ).Infof ("Tag event matches deleted image - removing reference" )
712
+ updatedTags .Insert (tag )
713
+ }
714
+ }
715
+ if len (newHistory .Items ) == 0 {
716
+ glog .V (4 ).Infof ("Removing tag %q from status.tags of ImageStream %s" , tag , getName (stream ))
717
+ delete (stream .Status .Tags , tag )
703
718
} else {
704
- glog .V (4 ).Infof ("Tag event matches deleted image - removing reference" )
705
- updatedTags .Insert (tag )
719
+ stream .Status .Tags [tag ] = newHistory
706
720
}
707
721
}
708
- if len (newHistory .Items ) == 0 {
709
- glog .V (4 ).Infof ("Removing tag %q from status.tags of ImageStream %s" , tag , getName (stream ))
710
- delete (stream .Status .Tags , tag )
711
- } else {
712
- stream .Status .Tags [tag ] = newHistory
713
- }
714
- }
715
722
716
- updatedStream , err := streamPruner .DeleteImageStream (stream , imageNode .Image , updatedTags .List ())
717
- if err != nil {
723
+ updatedStream , err := streamPruner .UpdateImageStream (stream , imageNode .Image , updatedTags .List ())
724
+ if err == nil {
725
+ streamNode .ImageStream = updatedStream
726
+ }
727
+ return err
728
+ }); err != nil {
718
729
errs = append (errs , fmt .Errorf ("error removing image %s from stream %s: %v" ,
719
- imageNode .Image .Name , getName (stream ), err ))
730
+ imageNode .Image .Name , getName (streamNode . ImageStream ), err ))
720
731
continue
721
732
}
722
-
723
- streamNode .ImageStream = updatedStream
724
733
}
725
734
}
726
735
glog .V (4 ).Infof ("Done removing pruned image references from streams" )
@@ -922,7 +931,11 @@ func NewImageStreamDeleter(streams client.ImageStreamsNamespacer) ImageStreamDel
922
931
}
923
932
}
924
933
925
- func (p * imageStreamDeleter ) DeleteImageStream (stream * imageapi.ImageStream , image * imageapi.Image , updatedTags []string ) (* imageapi.ImageStream , error ) {
934
+ func (p * imageStreamDeleter ) GetImageStream (stream * imageapi.ImageStream ) (* imageapi.ImageStream , error ) {
935
+ return p .streams .ImageStreams (stream .Namespace ).Get (stream .Name , metav1.GetOptions {})
936
+ }
937
+
938
+ func (p * imageStreamDeleter ) UpdateImageStream (stream * imageapi.ImageStream , image * imageapi.Image , updatedTags []string ) (* imageapi.ImageStream , error ) {
926
939
glog .V (4 ).Infof ("Updating ImageStream %s" , getName (stream ))
927
940
is , err := p .streams .ImageStreams (stream .Namespace ).UpdateStatus (stream )
928
941
if err == nil {
0 commit comments