Skip to content

Commit 7d83f5b

Browse files
author
OpenShift Bot
committed
Merge pull request #9163 from soltysh/import_all
Merged by openshift-bot
2 parents 0effc3c + fa40c7d commit 7d83f5b

File tree

2 files changed

+388
-209
lines changed

2 files changed

+388
-209
lines changed

pkg/cmd/cli/cmd/importimage.go

+162-107
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,13 @@ func (o *ImportImageOptions) Validate(cmd *cobra.Command) error {
129129

130130
// Run contains all the necessary functionality for the OpenShift cli import-image command.
131131
func (o *ImportImageOptions) Run() error {
132+
// TODO: add dry-run
132133
stream, isi, err := o.createImageImport()
133134
if err != nil {
134135
return err
135136
}
136137

137-
// TODO: add dry-run
138+
// Attempt the new, direct import path
138139
result, err := o.isClient.Import(isi)
139140
switch {
140141
case err == client.ErrImageStreamImportUnsupported:
@@ -248,128 +249,172 @@ func (o *ImportImageOptions) waitForImport(resourceVersion string) (*imageapi.Im
248249
}
249250

250251
func (o *ImportImageOptions) createImageImport() (*imageapi.ImageStream, *imageapi.ImageStreamImport, error) {
252+
var isi *imageapi.ImageStreamImport
251253
stream, err := o.isClient.Get(o.Name)
252-
from := o.From
253-
tag := o.Tag
254+
// no stream, try creating one
254255
if err != nil {
255256
if !errors.IsNotFound(err) {
256257
return nil, nil, err
257258
}
258-
259-
// the stream is new
260259
if !o.Confirm {
261260
return nil, nil, fmt.Errorf("no image stream named %q exists, pass --confirm to create and import", o.Name)
262261
}
263-
if len(from) == 0 {
264-
from = o.Target
265-
}
266-
if o.All {
267-
stream = &imageapi.ImageStream{
268-
ObjectMeta: kapi.ObjectMeta{Name: o.Name},
269-
Spec: imageapi.ImageStreamSpec{DockerImageRepository: from},
270-
}
271-
} else {
272-
stream = &imageapi.ImageStream{
273-
ObjectMeta: kapi.ObjectMeta{Name: o.Name},
274-
Spec: imageapi.ImageStreamSpec{
275-
Tags: map[string]imageapi.TagReference{
276-
tag: {
277-
From: &kapi.ObjectReference{
278-
Kind: "DockerImage",
279-
Name: from,
280-
},
281-
},
282-
},
283-
},
284-
}
285-
}
262+
stream, isi = o.newImageStream()
263+
return stream, isi, nil
264+
}
286265

266+
// the stream already exists
267+
if len(stream.Spec.DockerImageRepository) == 0 && len(stream.Spec.Tags) == 0 {
268+
return nil, nil, fmt.Errorf("image stream does not have valid docker images to be imported")
269+
}
270+
271+
if o.All {
272+
// importing the entire repository
273+
isi, err = o.importAll(stream)
274+
if err != nil {
275+
return nil, nil, err
276+
}
287277
} else {
288-
// the stream already exists
289-
if len(stream.Spec.DockerImageRepository) == 0 && len(stream.Spec.Tags) == 0 {
290-
return nil, nil, fmt.Errorf("image stream has not defined anything to import")
278+
// importing a single tag
279+
isi, err = o.importTag(stream)
280+
if err != nil {
281+
return nil, nil, err
291282
}
283+
}
292284

293-
if o.All {
294-
// importing a whole repository
295-
// TODO soltysh: write tests to cover all the possible usecases!!!
296-
if len(from) == 0 {
297-
if len(stream.Spec.DockerImageRepository) == 0 {
298-
// FIXME soltysh:
299-
return nil, nil, fmt.Errorf("flag --all is applicable only to images with spec.dockerImageRepository defined")
285+
return stream, isi, nil
286+
}
287+
288+
func (o *ImportImageOptions) importAll(stream *imageapi.ImageStream) (*imageapi.ImageStreamImport, error) {
289+
from := o.From
290+
// update ImageStream appropriately
291+
if len(from) == 0 {
292+
if len(stream.Spec.DockerImageRepository) != 0 {
293+
from = stream.Spec.DockerImageRepository
294+
} else {
295+
tags := make(map[string]string)
296+
for name, tag := range stream.Spec.Tags {
297+
if tag.From != nil && tag.From.Kind == "DockerImage" {
298+
tags[name] = tag.From.Name
300299
}
301-
from = stream.Spec.DockerImageRepository
302300
}
303-
if from != stream.Spec.DockerImageRepository {
304-
if !o.Confirm {
305-
if len(stream.Spec.DockerImageRepository) == 0 {
306-
return nil, nil, fmt.Errorf("the image stream does not currently import an entire Docker repository, pass --confirm to update")
307-
}
308-
return nil, nil, fmt.Errorf("the image stream has a different import spec %q, pass --confirm to update", stream.Spec.DockerImageRepository)
309-
}
310-
stream.Spec.DockerImageRepository = from
301+
if len(tags) == 0 {
302+
return nil, fmt.Errorf("image stream does not have tags pointing to external docker images")
311303
}
304+
return o.newImageStreamImportTags(stream, tags), nil
305+
}
306+
}
307+
if from != stream.Spec.DockerImageRepository {
308+
if !o.Confirm {
309+
if len(stream.Spec.DockerImageRepository) == 0 {
310+
return nil, fmt.Errorf("the image stream does not currently import an entire Docker repository, pass --confirm to update")
311+
}
312+
return nil, fmt.Errorf("the image stream has a different import spec %q, pass --confirm to update", stream.Spec.DockerImageRepository)
313+
}
314+
stream.Spec.DockerImageRepository = from
315+
}
312316

313-
} else {
314-
// importing a single tag
317+
// and create accompanying ImageStreamImport
318+
return o.newImageStreamImportAll(stream, from), nil
319+
}
315320

316-
// follow any referential tags to the destination
317-
finalTag, existing, ok, multiple := imageapi.FollowTagReference(stream, tag)
318-
if !ok && multiple {
319-
return nil, nil, fmt.Errorf("tag %q on the image stream is a reference to %q, which does not exist", tag, finalTag)
320-
}
321+
func (o *ImportImageOptions) importTag(stream *imageapi.ImageStream) (*imageapi.ImageStreamImport, error) {
322+
from := o.From
323+
tag := o.Tag
324+
// follow any referential tags to the destination
325+
finalTag, existing, ok, multiple := imageapi.FollowTagReference(stream, tag)
326+
if !ok && multiple {
327+
return nil, fmt.Errorf("tag %q on the image stream is a reference to %q, which does not exist", tag, finalTag)
328+
}
321329

322-
if ok {
323-
// disallow changing an existing tag
324-
if existing.From == nil || existing.From.Kind != "DockerImage" {
325-
return nil, nil, fmt.Errorf("tag %q already exists - you must use the 'tag' command if you want to change the source to %q", tag, from)
326-
}
327-
if len(from) != 0 && from != existing.From.Name {
328-
if multiple {
329-
return nil, nil, fmt.Errorf("the tag %q points to the tag %q which points to %q - use the 'tag' command if you want to change the source to %q", tag, finalTag, existing.From.Name, from)
330-
}
331-
return nil, nil, fmt.Errorf("the tag %q points to %q - use the 'tag' command if you want to change the source to %q", tag, existing.From.Name, from)
332-
}
330+
// update ImageStream appropriately
331+
if ok {
332+
// disallow changing an existing tag
333+
if existing.From == nil || existing.From.Kind != "DockerImage" {
334+
return nil, fmt.Errorf("tag %q already exists - you must use the 'tag' command if you want to change the source to %q", tag, from)
335+
}
336+
if len(from) != 0 && from != existing.From.Name {
337+
if multiple {
338+
return nil, fmt.Errorf("the tag %q points to the tag %q which points to %q - use the 'tag' command if you want to change the source to %q", tag, finalTag, existing.From.Name, from)
339+
}
340+
return nil, fmt.Errorf("the tag %q points to %q - use the 'tag' command if you want to change the source to %q", tag, existing.From.Name, from)
341+
}
333342

334-
// set the target item to import
335-
from = existing.From.Name
336-
if multiple {
337-
tag = finalTag
338-
}
343+
// set the target item to import
344+
from = existing.From.Name
345+
if multiple {
346+
tag = finalTag
347+
}
339348

340-
// clear the legacy annotation
341-
delete(existing.Annotations, imageapi.DockerImageRepositoryCheckAnnotation)
342-
// reset the generation
343-
zero := int64(0)
344-
existing.Generation = &zero
349+
// clear the legacy annotation
350+
delete(existing.Annotations, imageapi.DockerImageRepositoryCheckAnnotation)
351+
// reset the generation
352+
zero := int64(0)
353+
existing.Generation = &zero
345354

346-
} else {
347-
// create a new tag
348-
if len(from) == 0 {
349-
from = stream.Spec.DockerImageRepository
350-
}
351-
// if the from is still empty this means there's no such tag defined
352-
// nor we can't create any from .spec.dockerImageRepository
353-
if len(from) == 0 {
354-
return nil, nil, fmt.Errorf("the tag %q does not exist on the image stream - choose an existing tag to import or use the 'tag' command to create a new tag", tag)
355-
}
356-
existing = &imageapi.TagReference{
357-
From: &kapi.ObjectReference{
358-
Kind: "DockerImage",
359-
Name: from,
360-
},
361-
}
362-
}
363-
stream.Spec.Tags[tag] = *existing
355+
} else {
356+
// create a new tag
357+
if len(from) == 0 {
358+
from = stream.Spec.DockerImageRepository
359+
}
360+
// if the from is still empty this means there's no such tag defined
361+
// nor we can't create any from .spec.dockerImageRepository
362+
if len(from) == 0 {
363+
return nil, fmt.Errorf("the tag %q does not exist on the image stream - choose an existing tag to import or use the 'tag' command to create a new tag", tag)
364+
}
365+
existing = &imageapi.TagReference{
366+
From: &kapi.ObjectReference{
367+
Kind: "DockerImage",
368+
Name: from,
369+
},
364370
}
365371
}
372+
stream.Spec.Tags[tag] = *existing
366373

374+
// and create accompanying ImageStreamImport
375+
return o.newImageStreamImportTags(stream, map[string]string{tag: from}), nil
376+
}
377+
378+
func (o *ImportImageOptions) newImageStream() (*imageapi.ImageStream, *imageapi.ImageStreamImport) {
379+
from := o.From
380+
tag := o.Tag
367381
if len(from) == 0 {
368-
// catch programmer error
369-
return nil, nil, fmt.Errorf("unexpected error, from is empty")
382+
from = o.Target
383+
}
384+
var stream *imageapi.ImageStream
385+
// create new ImageStream
386+
if o.All {
387+
stream = &imageapi.ImageStream{
388+
ObjectMeta: kapi.ObjectMeta{Name: o.Name},
389+
Spec: imageapi.ImageStreamSpec{DockerImageRepository: from},
390+
}
391+
} else {
392+
stream = &imageapi.ImageStream{
393+
ObjectMeta: kapi.ObjectMeta{Name: o.Name},
394+
Spec: imageapi.ImageStreamSpec{
395+
Tags: map[string]imageapi.TagReference{
396+
tag: {
397+
From: &kapi.ObjectReference{
398+
Kind: "DockerImage",
399+
Name: from,
400+
},
401+
},
402+
},
403+
},
404+
}
405+
}
406+
// and accompanying ImageStreamImport
407+
var isi *imageapi.ImageStreamImport
408+
if o.All {
409+
isi = o.newImageStreamImportAll(stream, from)
410+
} else {
411+
isi = o.newImageStreamImportTags(stream, map[string]string{tag: from})
370412
}
371413

372-
// Attempt the new, direct import path
414+
return stream, isi
415+
}
416+
417+
func (o *ImportImageOptions) newImageStreamImport(stream *imageapi.ImageStream) (*imageapi.ImageStreamImport, bool) {
373418
isi := &imageapi.ImageStreamImport{
374419
ObjectMeta: kapi.ObjectMeta{
375420
Name: stream.Name,
@@ -384,15 +429,26 @@ func (o *ImportImageOptions) createImageImport() (*imageapi.ImageStream, *imagea
384429
if o.Insecure != nil {
385430
insecure = *o.Insecure
386431
}
387-
if o.All {
388-
isi.Spec.Repository = &imageapi.RepositoryImportSpec{
389-
From: kapi.ObjectReference{
390-
Kind: "DockerImage",
391-
Name: from,
392-
},
393-
ImportPolicy: imageapi.TagImportPolicy{Insecure: insecure},
394-
}
395-
} else {
432+
433+
return isi, insecure
434+
}
435+
436+
func (o *ImportImageOptions) newImageStreamImportAll(stream *imageapi.ImageStream, from string) *imageapi.ImageStreamImport {
437+
isi, insecure := o.newImageStreamImport(stream)
438+
isi.Spec.Repository = &imageapi.RepositoryImportSpec{
439+
From: kapi.ObjectReference{
440+
Kind: "DockerImage",
441+
Name: from,
442+
},
443+
ImportPolicy: imageapi.TagImportPolicy{Insecure: insecure},
444+
}
445+
446+
return isi
447+
}
448+
449+
func (o *ImportImageOptions) newImageStreamImportTags(stream *imageapi.ImageStream, tags map[string]string) *imageapi.ImageStreamImport {
450+
isi, insecure := o.newImageStreamImport(stream)
451+
for tag, from := range tags {
396452
isi.Spec.Images = append(isi.Spec.Images, imageapi.ImageImportSpec{
397453
From: kapi.ObjectReference{
398454
Kind: "DockerImage",
@@ -402,6 +458,5 @@ func (o *ImportImageOptions) createImageImport() (*imageapi.ImageStream, *imagea
402458
ImportPolicy: imageapi.TagImportPolicy{Insecure: insecure},
403459
})
404460
}
405-
406-
return stream, isi, nil
461+
return isi
407462
}

0 commit comments

Comments
 (0)