19eecaab12
With this changeset we introduce several new things. The first is the top-level dist command. This is a toolkit that implements various distribution primitives, such as fetching, unpacking and ingesting. The first component to this is a simple `fetch` command. It is a low-level command that takes a "remote", identified by a `locator`, and an object identifier. Keyed by the locator, this tool can identify a remote implementation to fetch the content and write it back to standard out. By allowing this to be the unit of pluggability in fetching content, we can have quite a bit of flexibility in how we retrieve images. The current `fetch` implementation provides anonymous access to docker hub images, through the namespace `docker.io`. As an example, one can fetch the manifest for `redis` with the following command: ``` $ ./dist fetch docker.io/library/redis latest mediatype:application/vnd.docker.distribution.manifest.v2+json ``` Note that we have provided a mediatype "hint", nudging the fetch implementation to grab the correct endpoint. We can hash the output of that to fetch the same content by digest: ``` $ ./dist fetch docker.io/library/redis sha256:$(./dist fetch docker.io/library/redis latest mediatype:application/vnd.docker.distribution.manifest.v2+json | shasum -a256) ``` Note that the hint is now elided, since we have affixed the content to a particular hash. If you are not yet entertained, let's bring `jq` and `xargs` into the mix for maximum fun. The following incantation fetches the same manifest and downloads all layers into the convenience of `/dev/null`: ``` $ ./dist fetch docker.io/library/redis sha256:a027a470aa2b9b41cc2539847a97b8a14794ebd0a4c7c5d64e390df6bde56c73 | jq -r '.layers[] | .digest' | xargs -n1 -P10 ./dist fetch docker.io/library/redis > /dev/null ``` This is just the beginning. We should be able to centralize configuration around fetch to implement a number of distribution methodologies that have been challenging or impossible up to this point. The `locator`, mentioned earlier, is a schemaless URL that provides a host and path that can be used to resolve the remote. By dispatching on this common identifier, we should be able to support almost any protocol and discovery mechanism imaginable. When this is more solidified, we can roll these up into higher-level operations that can be orchestrated through the `dist` tool or via GRPC. What a time to be alive! Signed-off-by: Stephen J Day <stephen.day@docker.com>
39 lines
1.4 KiB
Go
39 lines
1.4 KiB
Go
package remotes
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
)
|
|
|
|
type Remote interface {
|
|
// Fetch the resource identified by id. The id is opaque to the remote, but
|
|
// may typically be a tag or a digest.
|
|
//
|
|
// Hints are provided to give instruction on how the resource may be
|
|
// fetched. They may provide information about the expected type or size.
|
|
// They may be protocol specific or help a protocol to identify the most
|
|
// efficient fetch methodology.
|
|
//
|
|
// Hints are the format of `<type>:<content>` where `<type>` is the type
|
|
// of the hint and `<content>` can be pretty much anything. For example, a
|
|
// media type hint would be the following:
|
|
//
|
|
// mediatype:application/vnd.docker.distribution.manifest.v2+json
|
|
//
|
|
// The following hint names are must be honored across all remote
|
|
// implementations:
|
|
//
|
|
// size: specify the expected size in bytes
|
|
// mediatype: specify the expected mediatype
|
|
//
|
|
// The caller should never expect the hints to be honored and should
|
|
// validate that returned content is as expected. They are only provided to
|
|
// help the remote retrieve the content.
|
|
Fetch(ctx context.Context, id string, hints ...string) (io.ReadCloser, error)
|
|
}
|
|
|
|
type RemoteFunc func(context.Context, string, ...string) (io.ReadCloser, error)
|
|
|
|
func (fn RemoteFunc) Fetch(ctx context.Context, object string, hints ...string) (io.ReadCloser, error) {
|
|
return fn(ctx, object, hints...)
|
|
}
|