Esempio n. 1
0
// importTag import single tag from given ImageStream. Returns retrieved image (for later reuse),
// a flag saying if we should retry imports and an error if one occurs.
func (c *ImportController) importTag(stream *api.ImageStream, tag string, ref api.DockerImageReference, dockerImage *dockerregistry.Image, client dockerregistry.Client, insecure bool) (*dockerregistry.Image, bool, error) {
	glog.V(5).Infof("Importing tag %s from %s/%s...", tag, stream.Namespace, stream.Name)
	if dockerImage == nil {
		// TODO insecure applies to the stream's spec.dockerImageRepository, not necessarily to an external one!
		conn, err := client.Connect(ref.Registry, insecure)
		if err != nil {
			// retry-able error no. 3
			return nil, true, err
		}
		if len(ref.ID) > 0 {
			dockerImage, err = conn.ImageByID(ref.Namespace, ref.Name, ref.ID)
		} else {
			dockerImage, err = conn.ImageByTag(ref.Namespace, ref.Name, ref.Tag)
		}
		switch {
		case dockerregistry.IsRepositoryNotFound(err), dockerregistry.IsRegistryNotFound(err), dockerregistry.IsImageNotFound(err), dockerregistry.IsTagNotFound(err):
			return nil, false, err
		case err != nil:
			// retry-able error no. 4
			return nil, true, err
		}
	}
	var image api.DockerImage
	if err := kapi.Scheme.Convert(&dockerImage.Image, &image); err != nil {
		return nil, false, fmt.Errorf("could not convert image: %#v", err)
	}

	// prefer to pull by ID always
	if dockerImage.PullByID {
		// if the registry indicates the image is pullable by ID, clear the tag
		ref.Tag = ""
		ref.ID = dockerImage.ID
	}

	mapping := &api.ImageStreamMapping{
		ObjectMeta: kapi.ObjectMeta{
			Name:      stream.Name,
			Namespace: stream.Namespace,
		},
		Tag: tag,
		Image: api.Image{
			ObjectMeta: kapi.ObjectMeta{
				Name: dockerImage.ID,
			},
			DockerImageReference: ref.String(),
			DockerImageMetadata:  image,
		},
	}
	if err := c.mappings.ImageStreamMappings(stream.Namespace).Create(mapping); err != nil {
		// retry-able no. 5
		return nil, true, err
	}
	return dockerImage, false, nil
}
Esempio n. 2
0
// getTags returns tags from default upstream image repository and explicitly defined.
// Returns a map of tags to be imported and an error if one occurs.
// Tags explicitly defined will overwrite those from default upstream image repository.
func getTags(stream *api.ImageStream, client dockerregistry.Client, insecure bool) (map[string]api.DockerImageReference, error) {
	imports := make(map[string]api.DockerImageReference)
	references := sets.NewString()

	// read explicitly defined tags
	for tagName, specTag := range stream.Spec.Tags {
		if specTag.From == nil {
			continue
		}
		if specTag.From.Kind != "DockerImage" || specTag.Reference {
			references.Insert(tagName)
			continue
		}
		ref, err := api.ParseDockerImageReference(specTag.From.Name)
		if err != nil {
			glog.V(2).Infof("error parsing DockerImage %s: %v", specTag.From.Name, err)
			continue
		}
		imports[tagName] = ref.DockerClientDefaults()
	}

	if len(stream.Spec.DockerImageRepository) == 0 {
		return imports, nil
	}

	// read tags from default upstream image repository
	streamRef, err := api.ParseDockerImageReference(stream.Spec.DockerImageRepository)
	if err != nil {
		util.HandleError(fmt.Errorf("invalid docker image repository, cannot import data: %v", err))
		return imports, nil
	}
	conn, err := client.Connect(streamRef.Registry, insecure)
	if err != nil {
		// retry-able error no. 1
		return imports, err
	}
	tags, err := conn.ImageTags(streamRef.Namespace, streamRef.Name)
	switch {
	case dockerregistry.IsRepositoryNotFound(err), dockerregistry.IsRegistryNotFound(err):
		return imports, nil
	case err != nil:
		// retry-able error no. 2
		return imports, err
	}
	for tag, image := range tags {
		if _, ok := imports[tag]; ok || references.Has(tag) {
			continue
		}
		idTagPresent := false
		// this for loop is for backwards compatibility with v1 repo, where
		// there was no image id returned with tags, like v2 does right now.
		for t2, i2 := range tags {
			if i2 == image && t2 == image {
				idTagPresent = true
				break
			}
		}
		ref := streamRef
		if idTagPresent {
			ref.Tag = image
		} else {
			ref.Tag = tag
		}
		ref.ID = image
		imports[tag] = ref
	}

	return imports, nil
}