Skip to content

Commit 6ed62a6

Browse files
Update openshift image layers API
1 parent 96c75d7 commit 6ed62a6

File tree

8 files changed

+89
-22
lines changed

8 files changed

+89
-22
lines changed

api/protobuf-spec/github_com_openshift_api_image_v1.proto

+11-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/swagger-spec/openshift-openapi-spec.json

+9-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/image/apis/image/types.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -486,15 +486,21 @@ type ImageStreamLayers struct {
486486

487487
// ImageBlobReferences describes the blob references within an image.
488488
type ImageBlobReferences struct {
489+
// imageMissing is true if the image is referenced by the image stream but the image
490+
// object has been deleted from the API by an administrator. When this field is set,
491+
// layers and config fields may be empty and callers that depend on the image metadata
492+
// should consider the image to be unavailable for download or viewing.
493+
// +optional
494+
ImageMissing bool
489495
// layers is the list of blobs that compose this image, from base layer to top layer.
490496
// All layers referenced by this array will be defined in the blobs map. Some images
491497
// may have zero layers.
492498
// +optional
493499
Layers []string
494-
// manifest, if set, is the blob that contains the image manifest. Some images do
500+
// config, if set, is the blob that contains the image configuration. Some images do
495501
// not have separate manifest blobs and this field will be set to nil if so.
496502
// +optional
497-
Manifest *string
503+
Config *string
498504
}
499505

500506
// ImageLayerData contains metadata about an image layer.

pkg/image/apis/image/v1/zz_generated.conversion.go

+4-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/image/apis/image/zz_generated.deepcopy.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/image/apiserver/registry/imagestream/etcd/etcd.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ func addImageStreamLayersFromCache(isl *imageapi.ImageStreamLayers, is *imageapi
206206
obj, _, _ := index.GetByKey(item.Image)
207207
entry, ok := obj.(*ImageLayers)
208208
if !ok {
209+
if _, ok := isl.Images[item.Image]; !ok {
210+
isl.Images[item.Image] = imageapi.ImageBlobReferences{ImageMissing: true}
211+
}
209212
missing = append(missing, item.Image)
210213
continue
211214
}
@@ -224,7 +227,7 @@ func addImageStreamLayersFromCache(isl *imageapi.ImageStreamLayers, is *imageapi
224227
}
225228

226229
if blob := entry.Config; blob != nil {
227-
reference.Manifest = &blob.Name
230+
reference.Config = &blob.Name
228231
if _, ok := isl.Blobs[blob.Name]; !ok {
229232
if blob.LayerSize == 0 {
230233
// only send media type since we don't the size of the manifest

pkg/openapi/zz_generated.openapi.go

+10-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/extended/images/layers.go

+41-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,44 @@ var _ = g.Describe("[Feature:ImageLayers] Image layer subresource", func() {
3434

3535
oc = exutil.NewCLI("image-layers", exutil.KubeConfigPath())
3636

37+
g.It("should identify a deleted image as missing", func() {
38+
client := imageclientset.NewForConfigOrDie(oc.AdminConfig()).Image()
39+
_, err := client.ImageStreams(oc.Namespace()).Create(&imageapi.ImageStream{
40+
ObjectMeta: metav1.ObjectMeta{
41+
Name: "test",
42+
},
43+
})
44+
o.Expect(err).NotTo(o.HaveOccurred())
45+
_, err = client.ImageStreamMappings(oc.Namespace()).Create(&imageapi.ImageStreamMapping{
46+
ObjectMeta: metav1.ObjectMeta{
47+
Name: "test",
48+
},
49+
Image: imageapi.Image{
50+
ObjectMeta: metav1.ObjectMeta{
51+
Name: "an_image_to_be_deleted",
52+
},
53+
DockerImageReference: "example.com/random/image:latest",
54+
},
55+
Tag: "missing",
56+
})
57+
o.Expect(err).NotTo(o.HaveOccurred())
58+
err = client.Images().Delete("an_image_to_be_deleted", nil)
59+
o.Expect(err).NotTo(o.HaveOccurred())
60+
err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
61+
layers, err := client.ImageStreams(oc.Namespace()).Layers("test", metav1.GetOptions{})
62+
if err != nil {
63+
return false, err
64+
}
65+
ref, ok := layers.Images["an_image_to_be_deleted"]
66+
if !ok {
67+
return false, nil
68+
}
69+
o.Expect(ref.ImageMissing).To(o.BeTrue())
70+
return true, nil
71+
})
72+
o.Expect(err).NotTo(o.HaveOccurred())
73+
})
74+
3775
g.It("should return layers from tagged images", func() {
3876
ns = []string{oc.Namespace()}
3977
client := imageclientset.NewForConfigOrDie(oc.UserConfig()).Image()
@@ -71,9 +109,9 @@ var _ = g.Describe("[Feature:ImageLayers] Image layer subresource", func() {
71109
l, ok := layers.Images[image.Image.Name]
72110
o.Expect(ok).To(o.BeTrue())
73111
o.Expect(len(l.Layers)).To(o.BeNumerically(">", 0))
74-
o.Expect(l.Manifest).ToNot(o.BeNil())
75-
o.Expect(layers.Blobs[*l.Manifest]).ToNot(o.BeNil())
76-
o.Expect(layers.Blobs[*l.Manifest].MediaType).To(o.Equal("application/vnd.docker.container.image.v1+json"))
112+
o.Expect(l.Config).ToNot(o.BeNil())
113+
o.Expect(layers.Blobs[*l.Config]).ToNot(o.BeNil())
114+
o.Expect(layers.Blobs[*l.Config].MediaType).To(o.Equal("application/vnd.docker.container.image.v1+json"))
77115
for _, layerID := range l.Layers {
78116
o.Expect(layers.Blobs).To(o.HaveKey(layerID))
79117
o.Expect(layers.Blobs[layerID].MediaType).NotTo(o.BeEmpty())

0 commit comments

Comments
 (0)