Example #1
0
// tagNeedsImport is true if the observed tag generation for this tag is older than the
// specified tag generation (if no tag generation is specified, the controller does not
// need to import this tag).
func tagNeedsImport(stream *api.ImageStream, tag string, tagRef api.TagReference, importWhenGenerationNil bool) bool {
	if !tagImportable(tagRef) {
		return false
	}
	if tagRef.Generation == nil {
		return importWhenGenerationNil
	}
	return *tagRef.Generation > api.LatestObservedTagGeneration(stream, tag)
}
Example #2
0
func formatImageStreamTags(out *tabwriter.Writer, stream *imageapi.ImageStream) {
	if len(stream.Status.Tags) == 0 && len(stream.Spec.Tags) == 0 {
		fmt.Fprintf(out, "Tags:\t<none>\n")
		return
	}

	now := timeNowFn()

	images := make(map[string]string)
	for tag, tags := range stream.Status.Tags {
		for _, item := range tags.Items {
			switch {
			case len(item.Image) > 0:
				if _, ok := images[item.Image]; !ok {
					images[item.Image] = tag
				}
			case len(item.DockerImageReference) > 0:
				if _, ok := images[item.DockerImageReference]; !ok {
					images[item.Image] = item.DockerImageReference
				}
			}
		}
	}

	sortedTags := []string{}
	for k := range stream.Status.Tags {
		sortedTags = append(sortedTags, k)
	}
	var localReferences sets.String
	var referentialTags map[string]sets.String
	for k := range stream.Spec.Tags {
		if target, _, ok, multiple := imageapi.FollowTagReference(stream, k); ok && multiple {
			if referentialTags == nil {
				referentialTags = make(map[string]sets.String)
			}
			if localReferences == nil {
				localReferences = sets.NewString()
			}
			localReferences.Insert(k)
			v := referentialTags[target]
			if v == nil {
				v = sets.NewString()
				referentialTags[target] = v
			}
			v.Insert(k)
		}
		if _, ok := stream.Status.Tags[k]; !ok {
			sortedTags = append(sortedTags, k)
		}
	}
	fmt.Fprintf(out, "Unique Images:\t%d\nTags:\t%d\n\n", len(images), len(sortedTags))

	first := true
	imageapi.PrioritizeTags(sortedTags)
	for _, tag := range sortedTags {
		if localReferences.Has(tag) {
			continue
		}
		if first {
			first = false
		} else {
			fmt.Fprintf(out, "\n")
		}
		taglist, _ := stream.Status.Tags[tag]
		tagRef, hasSpecTag := stream.Spec.Tags[tag]
		scheduled := false
		insecure := false
		importing := false

		var name string
		if hasSpecTag && tagRef.From != nil {
			if len(tagRef.From.Namespace) > 0 && tagRef.From.Namespace != stream.Namespace {
				name = fmt.Sprintf("%s/%s", tagRef.From.Namespace, tagRef.From.Name)
			} else {
				name = tagRef.From.Name
			}
			scheduled, insecure = tagRef.ImportPolicy.Scheduled, tagRef.ImportPolicy.Insecure
			gen := imageapi.LatestObservedTagGeneration(stream, tag)
			importing = !tagRef.Reference && tagRef.Generation != nil && *tagRef.Generation != gen
		}

		//   updates whenever tag :5.2 is changed

		// :latest (30 minutes ago) -> 102.205.358.453/foo/bar@sha256:abcde734
		//   error: last import failed 20 minutes ago
		//   updates automatically from index.docker.io/mysql/bar
		//     will use insecure HTTPS connections or HTTP
		//
		//   MySQL 5.5
		//   ---------
		//   Describes a system for updating based on practical changes to a database system
		//   with some other data involved
		//
		//   20 minutes ago  <import failed>
		//	  	Failed to locate the server in time
		//   30 minutes ago  102.205.358.453/foo/bar@sha256:abcdef
		//   1 hour ago      102.205.358.453/foo/bar@sha256:bfedfc

		//var shortErrors []string
		/*
			var internalReference *imageapi.DockerImageReference
			if value := stream.Status.DockerImageRepository; len(value) > 0 {
				ref, err := imageapi.ParseDockerImageReference(value)
				if err != nil {
					internalReference = &ref
				}
			}
		*/

		if referentialTags[tag].Len() > 0 {
			references := referentialTags[tag].List()
			imageapi.PrioritizeTags(references)
			fmt.Fprintf(out, "%s (%s)\n", tag, strings.Join(references, ", "))
		} else {
			fmt.Fprintf(out, "%s\n", tag)
		}

		switch {
		case !hasSpecTag || tagRef.From == nil:
			fmt.Fprintf(out, "  pushed image\n")
		case tagRef.From.Kind == "ImageStreamTag":
			switch {
			case tagRef.Reference:
				fmt.Fprintf(out, "  reference to %s\n", name)
			case scheduled:
				fmt.Fprintf(out, "  updates automatically from %s\n", name)
			default:
				fmt.Fprintf(out, "  tagged from %s\n", name)
			}
		case tagRef.From.Kind == "DockerImage":
			switch {
			case tagRef.Reference:
				fmt.Fprintf(out, "  reference to registry %s\n", name)
			case scheduled:
				fmt.Fprintf(out, "  updates automatically from registry %s\n", name)
			default:
				fmt.Fprintf(out, "  tagged from %s\n", name)
			}
		case tagRef.From.Kind == "ImageStreamImage":
			switch {
			case tagRef.Reference:
				fmt.Fprintf(out, "  reference to image %s\n", name)
			default:
				fmt.Fprintf(out, "  tagged from %s\n", name)
			}
		default:
			switch {
			case tagRef.Reference:
				fmt.Fprintf(out, "  reference to %s %s\n", tagRef.From.Kind, name)
			default:
				fmt.Fprintf(out, "  updates from %s %s\n", tagRef.From.Kind, name)
			}
		}
		if insecure {
			fmt.Fprintf(out, "    will use insecure HTTPS or HTTP connections\n")
		}

		fmt.Fprintln(out)

		extraOutput := false
		if d := tagRef.Annotations["description"]; len(d) > 0 {
			fmt.Fprintf(out, "  %s\n", d)
			extraOutput = true
		}
		if t := tagRef.Annotations["tags"]; len(t) > 0 {
			fmt.Fprintf(out, "  Tags: %s\n", strings.Join(strings.Split(t, ","), ", "))
			extraOutput = true
		}
		if t := tagRef.Annotations["supports"]; len(t) > 0 {
			fmt.Fprintf(out, "  Supports: %s\n", strings.Join(strings.Split(t, ","), ", "))
			extraOutput = true
		}
		if t := tagRef.Annotations["sampleRepo"]; len(t) > 0 {
			fmt.Fprintf(out, "  Example Repo: %s\n", t)
			extraOutput = true
		}
		if extraOutput {
			fmt.Fprintln(out)
		}

		if importing {
			fmt.Fprintf(out, "  ~ importing latest image ...\n")
		}

		for i := range taglist.Conditions {
			condition := &taglist.Conditions[i]
			switch condition.Type {
			case imageapi.ImportSuccess:
				if condition.Status == api.ConditionFalse {
					d := now.Sub(condition.LastTransitionTime.Time)
					fmt.Fprintf(out, "  ! error: Import failed (%s): %s\n      %s ago\n", condition.Reason, condition.Message, units.HumanDuration(d))
				}
			}
		}

		if len(taglist.Items) == 0 {
			continue
		}

		for i, event := range taglist.Items {
			d := now.Sub(event.Created.Time)

			if i == 0 {
				fmt.Fprintf(out, "  * %s\n", event.DockerImageReference)
			} else {
				fmt.Fprintf(out, "    %s\n", event.DockerImageReference)
			}

			ref, err := imageapi.ParseDockerImageReference(event.DockerImageReference)
			id := event.Image
			if len(id) > 0 && err == nil && ref.ID != id {
				fmt.Fprintf(out, "      %s ago\t%s\n", units.HumanDuration(d), id)
			} else {
				fmt.Fprintf(out, "      %s ago\n", units.HumanDuration(d))
			}
		}
	}
}