Skip to content

Commit b4bb2f7

Browse files
soltyshMichal Minář
authored and
Michal Minář
committed
Retry image stream updates when pruning images
1 parent c5b4bc8 commit b4bb2f7

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

pkg/cmd/admin/prune/images.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,11 @@ type describingImageStreamDeleter struct {
361361

362362
var _ prune.ImageStreamDeleter = &describingImageStreamDeleter{}
363363

364-
func (p *describingImageStreamDeleter) DeleteImageStream(stream *imageapi.ImageStream, image *imageapi.Image, updatedTags []string) (*imageapi.ImageStream, error) {
364+
func (p *describingImageStreamDeleter) GetImageStream(stream *imageapi.ImageStream) (*imageapi.ImageStream, error) {
365+
return stream, nil
366+
}
367+
368+
func (p *describingImageStreamDeleter) UpdateImageStream(stream *imageapi.ImageStream, image *imageapi.Image, updatedTags []string) (*imageapi.ImageStream, error) {
365369
if !p.headerPrinted {
366370
p.headerPrinted = true
367371
fmt.Fprintln(p.w, "Deleting references from image streams to images ...")
@@ -374,7 +378,7 @@ func (p *describingImageStreamDeleter) DeleteImageStream(stream *imageapi.ImageS
374378
return stream, nil
375379
}
376380

377-
updatedStream, err := p.delegate.DeleteImageStream(stream, image, updatedTags)
381+
updatedStream, err := p.delegate.UpdateImageStream(stream, image, updatedTags)
378382
if err != nil {
379383
fmt.Fprintf(os.Stderr, "error updating image stream %s/%s to remove references to image %s: %v\n", stream.Namespace, stream.Name, image.Name, err)
380384
}

pkg/image/prune/prune.go

+42-29
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
kerrors "k8s.io/apimachinery/pkg/util/errors"
2121
"k8s.io/apimachinery/pkg/util/sets"
2222
kapi "k8s.io/kubernetes/pkg/api"
23+
"k8s.io/kubernetes/pkg/client/retry"
2324

2425
"github.com/openshift/origin/pkg/api/graph"
2526
kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
@@ -71,9 +72,11 @@ type ImageDeleter interface {
7172

7273
// ImageStreamDeleter knows how to remove an image reference from an image stream.
7374
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
7578
// 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)
7780
}
7881

7982
// BlobDeleter knows how to delete a blob from the Docker registry.
@@ -671,7 +674,7 @@ func calculatePrunableImageComponents(g graph.Graph) []*imagegraph.ImageComponen
671674
}
672675

673676
// 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
675678
// stream.
676679
func pruneStreams(g graph.Graph, imageNodes []*imagegraph.ImageNode, streamPruner ImageStreamDeleter) []error {
677680
errs := []error{}
@@ -684,43 +687,49 @@ func pruneStreams(g graph.Graph, imageNodes []*imagegraph.ImageNode, streamPrune
684687
continue
685688
}
686689

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()
689696

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)
691698

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)
694701

695-
newHistory := imageapi.TagEventList{}
702+
newHistory := imageapi.TagEventList{}
696703

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)
699706

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)
703718
} else {
704-
glog.V(4).Infof("Tag event matches deleted image - removing reference")
705-
updatedTags.Insert(tag)
719+
stream.Status.Tags[tag] = newHistory
706720
}
707721
}
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-
}
715722

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 {
718729
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))
720731
continue
721732
}
722-
723-
streamNode.ImageStream = updatedStream
724733
}
725734
}
726735
glog.V(4).Infof("Done removing pruned image references from streams")
@@ -922,7 +931,11 @@ func NewImageStreamDeleter(streams client.ImageStreamsNamespacer) ImageStreamDel
922931
}
923932
}
924933

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) {
926939
glog.V(4).Infof("Updating ImageStream %s", getName(stream))
927940
is, err := p.streams.ImageStreams(stream.Namespace).UpdateStatus(stream)
928941
if err == nil {

pkg/image/prune/prune_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,11 @@ type fakeImageStreamDeleter struct {
365365

366366
var _ ImageStreamDeleter = &fakeImageStreamDeleter{}
367367

368-
func (p *fakeImageStreamDeleter) DeleteImageStream(stream *imageapi.ImageStream, image *imageapi.Image, updatedTags []string) (*imageapi.ImageStream, error) {
368+
func (p *fakeImageStreamDeleter) GetImageStream(stream *imageapi.ImageStream) (*imageapi.ImageStream, error) {
369+
return stream, p.err
370+
}
371+
372+
func (p *fakeImageStreamDeleter) UpdateImageStream(stream *imageapi.ImageStream, image *imageapi.Image, updatedTags []string) (*imageapi.ImageStream, error) {
369373
p.invocations.Insert(fmt.Sprintf("%s/%s|%s", stream.Namespace, stream.Name, image.Name))
370374
return stream, p.err
371375
}

0 commit comments

Comments
 (0)