func (fetcher *DockerRepositoryFetcher) fetchFromEndpoint(endpoint string, imgID string, token []string) error {
	history, err := fetcher.registry.GetRemoteHistory(imgID, endpoint, token)
	if err != nil {
		return err
	}

	for i := len(history) - 1; i >= 0; i-- {
		id := history[i]

		if fetcher.graph.Exists(id) {
			log.Println("already exists:", id)
			continue
		}

		imgJSON, _, err := fetcher.registry.GetRemoteImageJSON(id, endpoint, token)
		if err != nil {
			return err
		}

		img, err := image.NewImgJSON(imgJSON)
		if err != nil {
			return err
		}

		layer, err := fetcher.registry.GetRemoteImageLayer(img.ID, endpoint, token)
		if err != nil {
			return err
		}

		defer layer.Close()

		log.Println("downloading layer:", id)

		err = fetcher.graph.Register(imgJSON, layer, img)
		if err != nil {
			return err
		}
	}

	return nil
}
Beispiel #2
0
// CmdSet stores a new image in the graph.
// Images are stored in the graph using 4 elements:
//	- A user-defined ID
//	- A collection of metadata describing the image
//	- A directory tree stored as a tar archive (also called the "layer")
//	- A reference to a "parent" ID on top of which the layer should be applied
//
// NOTE: even though the parent ID is only useful in relation to the layer and how
// to apply it (ie you could represent the full directory tree as 'parent_layer + layer',
// it is treated as a top-level property of the image. This is an artifact of early
// design and should probably be cleaned up in the future to simplify the design.
//
// Syntax: image_set ID
// Input:
//	- Layer content must be streamed in tar format on stdin. An empty input is
//	valid and represents a nil layer.
//
//	- Image metadata must be passed in the command environment.
//		'json': a json-encoded object with all image metadata.
//			It will be stored as-is, without any encoding/decoding artifacts.
//			That is a requirement of the current registry client implementation,
//			because a re-encoded json might invalidate the image checksum at
//			the next upload, even with functionaly identical content.
func (s *TagStore) CmdSet(job *engine.Job) engine.Status {
	if len(job.Args) != 1 {
		return job.Errorf("usage: %s NAME", job.Name)
	}
	var (
		imgJSON = []byte(job.Getenv("json"))
		layer   = job.Stdin
	)
	if len(imgJSON) == 0 {
		return job.Errorf("mandatory key 'json' is not set")
	}
	// We have to pass an *image.Image object, even though it will be completely
	// ignored in favor of the redundant json data.
	// FIXME: the current prototype of Graph.Register is stupid and redundant.
	img, err := image.NewImgJSON(imgJSON)
	if err != nil {
		return job.Error(err)
	}
	if err := s.graph.Register(imgJSON, layer, img); err != nil {
		return job.Error(err)
	}
	return engine.StatusOK
}