distribution

package
v0.0.0-...-a72880a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 21, 2024 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// RoutePing is the route descriptor to ping registry.
	RoutePing = RouteDescriptor{
		ID:           "end-1",
		Method:       http.MethodGet,
		PathPattern:  "/v2/",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound, http.StatusUnauthorized},
	}
	// RouteTagsList is the route descriptor for the tags to list.
	RouteTagsList = RouteDescriptor{
		ID:           "end-8a",
		Method:       http.MethodGet,
		PathPattern:  "/v2/{name}/tags/list",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteTagsListPager is the route descriptor for the tags to list with page query parameters.
	// Example: GET /v2/{name}/tags/list?n={integer}&last={tagname}
	RouteTagsListPager = RouteDescriptor{
		ID:          "end-8b",
		Method:      http.MethodGet,
		PathPattern: "/v2/{name}/tags/list",
		QueryParams: map[string]string{
			"n":    "{integer}",
			"last": "{tagname}",
		},
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteReferrersList is the route descriptor for the referrers to list.
	RouteReferrersList = RouteDescriptor{
		ID:           "end-12a",
		Method:       http.MethodGet,
		PathPattern:  "/v2/{name}/referrers/{digest}",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound, http.StatusBadRequest},
	}
	// RouteReferrersListByType is the route descriptor for the referrers to list by artifact type.
	// Example: GET /v2/{name}/referrers/{digest}?artifactType={artifactType}
	RouteReferrersListByType = RouteDescriptor{
		ID:          "end-12b",
		Method:      http.MethodGet,
		PathPattern: "/v2/{name}/referrers/{digest}",
		QueryParams: map[string]string{
			"artifactType": "{artifactType}",
		},
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound, http.StatusBadRequest},
	}
)

ping, tags, referrers related endpoints.

View Source
var (
	// RouteManifestsGet is the route descriptor for the manifests to fetch.
	RouteManifestsGet = RouteDescriptor{
		ID:           "end-3",
		Method:       http.MethodGet,
		PathPattern:  "/v2/{name}/manifests/{reference}",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteManifestsHead is the route descriptor for the manifests to stat.
	RouteManifestsHead = RouteDescriptor{
		ID:           "end-3",
		Method:       http.MethodHead,
		PathPattern:  "/v2/{name}/manifests/{reference}",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteManifestsPut is the route descriptor for the manifests to upload.
	RouteManifestsPut = RouteDescriptor{
		ID:           "end-7",
		Method:       http.MethodPut,
		PathPattern:  "/v2/{name}/manifests/{reference}",
		SuccessCodes: []int{http.StatusCreated},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteManifestsDelete is the route descriptor for the manifests to delete.
	RouteManifestsDelete = RouteDescriptor{
		ID:           "end-9",
		Method:       http.MethodDelete,
		PathPattern:  "/v2/{name}/manifests/{reference}",
		SuccessCodes: []int{http.StatusAccepted},
		FailureCodes: []int{
			http.StatusNotFound,
			http.StatusBadRequest,
			http.StatusMethodNotAllowed,
		},
	}
)

manifests related endpoints.

View Source
var (
	// RouteBlobsGet is the route descriptor for the blobs to fetch.
	RouteBlobsGet = RouteDescriptor{
		ID:           "end-2",
		Method:       http.MethodGet,
		PathPattern:  "/v2/{name}/manifests/{digest}",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteBlobsHead is the route descriptor for the blobs to stat.
	RouteBlobsHead = RouteDescriptor{
		ID:           "end-2",
		Method:       http.MethodHead,
		PathPattern:  "/v2/{name}/manifests/{digest}",
		SuccessCodes: []int{http.StatusOK},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteBlobsUploadStart is the route descriptor for the blobs to start blob uploads.
	RouteBlobsUploadStart = RouteDescriptor{
		ID:           "end-4a",
		Method:       http.MethodPost,
		PathPattern:  "/v2/{name}/blobs/uploads/",
		SuccessCodes: []int{http.StatusAccepted},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteBlobsUploadBlob is the route descriptor for the blobs to upload blobs.
	// Example: POST /v2/{name}/blobs/uploads/?digest={digest}
	RouteBlobsUploadBlob = RouteDescriptor{
		ID:          "end-4b",
		Method:      http.MethodPost,
		PathPattern: "/v2/{name}/blobs/uploads/",
		QueryParams: map[string]string{
			"digest": "{digest}",
		},
		SuccessCodes: []int{http.StatusCreated, http.StatusAccepted},
		FailureCodes: []int{http.StatusNotFound, http.StatusBadRequest},
	}
	// RouteBlobsUploadChunk is the route descriptor for the blobs to upload chunks.
	RouteBlobsUploadChunk = RouteDescriptor{
		ID:           "end-5",
		Method:       http.MethodPatch,
		PathPattern:  "/v2/{name}/blobs/uploads/{reference}",
		SuccessCodes: []int{http.StatusAccepted},
		FailureCodes: []int{
			http.StatusNotFound,
			http.StatusRequestedRangeNotSatisfiable,
		},
	}
	// RouteBlobsUploadComplete is the route descriptor for the blobs to complete blob uploads.
	// Example: PUT /v2/{name}/blobs/uploads/{reference}?digest={digest}
	RouteBlobsUploadComplete = RouteDescriptor{
		ID:          "end-6",
		Method:      http.MethodPut,
		PathPattern: "/v2/{name}/blobs/uploads/{reference}",
		QueryParams: map[string]string{
			"digest": "{digest}",
		},
		SuccessCodes: []int{http.StatusCreated},
		FailureCodes: []int{http.StatusNotFound, http.StatusBadRequest},
	}
	// RouteBlobsDelete is the route descriptor for the blobs to delete.
	RouteBlobsDelete = RouteDescriptor{
		ID:           "end-10",
		Method:       http.MethodDelete,
		PathPattern:  "/v2/{name}/blobs/{digest}",
		SuccessCodes: []int{http.StatusAccepted},
		FailureCodes: []int{http.StatusNotFound, http.StatusMethodNotAllowed},
	}
	// RouteBlobsMount is the route descriptor for blobs to mount.
	// Example: POST /v2/{name}/blobs/uploads/?mount={digest}&from={other_name}
	RouteBlobsMount = RouteDescriptor{
		ID:          "end-11",
		Method:      http.MethodPost,
		PathPattern: "/v2/{name}/blobs/uploads/",
		QueryParams: map[string]string{
			"mount": "{digest}",
			"from":  "{name}",
		},
		SuccessCodes: []int{http.StatusCreated},
		FailureCodes: []int{http.StatusNotFound},
	}
	// RouteBlobsStatUploadsInfo is the route descriptor for the blobs to stat uploads info.
	RouteBlobsStatUploadsInfo = RouteDescriptor{
		ID:           "end-13",
		Method:       http.MethodGet,
		PathPattern:  "/v2/{name}/blobs/uploads/{session_id}",
		SuccessCodes: []int{http.StatusNoContent},
		FailureCodes: []int{http.StatusNotFound},
	}
)

blobs related endpoints.

View Source
var (
	// DefaultClient is the default client with the memory-based cache.
	DefaultClient = &Client{
		ChallengeCache: xcache.NewMemory[authn.Challenge](),
		TokenCache:     xcache.NewMemory[authn.Token](),
	}
)

Functions

func HTTPSuccess

func HTTPSuccess(resp *http.Response, allowedCodes ...int) error

HTTPSuccess returns nil if the response status code is allowed, or an error parsed from response.

NOTE: This method will try to read resp.Body but not close it, so that the caller are expected to close resp.Body manully.

Types

type AuthProvider

type AuthProvider func(ctx context.Context, host string) authn.AuthConfig

AuthProvider provides the AuthConfig related to the registry.

type BlobWriteCloser

type BlobWriteCloser interface {
	// Write writes more data to the blob. When resuming, the
	// caller must start writing data from Size bytes into the content.
	io.Writer

	// Closer closes the writer but does not abort. The blob write
	// can later be resumed.
	io.Closer

	// Size returns the number of bytes written to this blob.
	Size() int64

	// ChunkSize returns the maximum number of bytes to upload at a single time.
	// This number must meet the minimum given by the registry
	// and should otherwise follow the hint given by the user.
	ChunkSize() int

	// ID returns the opaque identifier for this writer. The returned value
	// can be passed to PushBlobChunked to resume the write.
	// It is only valid before Write has been called or after Close has
	// been called.
	ID() string

	// Commit completes the blob writer process. The content is verified
	// against the provided digest, and a canonical descriptor for it is returned.
	Commit(digest digest.Digest) (v1.Descriptor, error)

	// Cancel ends the blob write without storing any data and frees any
	// associated resources. Any data written thus far will be lost. Cancel
	// implementations should allow multiple calls even after a commit that
	// result in a no-op. This allows use of Cancel in a defer statement,
	// increasing the assurance that it is correctly called.
	Cancel() error
}

BlobWriteCloser provides a handle for uploading a blob to a registry.

type ChallengeCache

type ChallengeCache = xcache.Cache[authn.Challenge]

ChallengeCache is the cache for the Challenge related to the registry.

type Client

type Client struct {
	// Client is the underlying HTTP client used to access the remote
	// server. If nil, http.DefaultClient is used.
	Client *http.Client

	// Header contains the custom headers to be added to each request.
	Header http.Header

	// AuthProvider returns AuthConfig related to the registry, which just returns an
	// empty AuthConfig when not found.
	AuthProvider AuthProvider

	// ChallengeCache is the cache for Challenge related to the registry, if not set,
	// default to a cache which will discard all operations.
	ChallengeCache ChallengeCache

	// TokenCache is the cache for Token related to the registry and scopes, if not set,
	// default to a cache which will discard all operations
	TokenCache TokenCache

	// TokenOptions is the options to fetch token for authorization.
	TokenOptions TokenOptions
}

func (*Client) Do

func (c *Client) Do(request *http.Request) (*http.Response, error)

Do performs an HTTP request and returns an HTTP response with additinal processes like authenticating the request.

func (*Client) NewRegistry

func (c *Client) NewRegistry(addr string) (*RegistryClient, error)

func (*Client) NewRegistryWithContext

func (c *Client) NewRegistryWithContext(ctx context.Context, addr string) (*RegistryClient, error)

type Deleter

type Deleter interface {
	// DeleteBlob deletes the blob with the given digest in the given repository.
	DeleteBlob(ctx context.Context, repo string, dgst digest.Digest) error

	// DeleteManifest deletes the manifest with the given digest in the given repository.
	DeleteManifest(ctx context.Context, repo string, dgst digest.Digest) error

	// DeleteTag deletes the manifest with the given tag in the given repository.
	//
	// FIXME(wuxler): does this delete the tag only, or the manifest too?
	DeleteTag(ctx context.Context, repo string, tag string) error
}

Deleter defines registry delete actions that for blobs, manifests and other resources.

type Describable

type Describable interface {
	// Descriptor returns the descriptor for the resource.
	Descriptor() v1.Descriptor
}

Describable defines a registry resource that can be described.

type DescribableReadCloser

type DescribableReadCloser interface {
	Describable
	io.ReadCloser
}

DescribableReadCloser provides the contents of a given blob or manifest.

func NewDescribableReadCloser

func NewDescribableReadCloser(rc io.ReadCloser, desc v1.Descriptor) DescribableReadCloser

NewDescribableReadCloser returns a DescribableReadCloser with the descriptor.

func NewDescribableReadCloserSkipVerify

func NewDescribableReadCloserSkipVerify(rc io.ReadCloser, desc v1.Descriptor) DescribableReadCloser

NewDescribableReadCloserSkipVerify returns a DescribableReadCloser with skip digest and size verification on Read().

type Lister

type Lister interface {
	// Repositories returns an iterator that can be used to iterate
	// over all the repositories in the registry in lexical order.
	// If startAfter is non-empty, the iteration starts lexically
	// after, but not including, that repository.
	Repositories(ctx context.Context, startAfter string) iter.Seq[string]

	// Tags returns an iterator that can be used to iterate over all
	// the tags in the given repository in lexical order. If
	// startAfter is non-empty, the tags start lexically after, but
	// not including that tag.
	Tags(ctx context.Context, repo string, startAfter string) iter.Seq[string]

	// Referrers returns an iterator that can be used to iterate over all
	// the manifests that have the given digest as their Subject.
	// If artifactType is non-zero, the results will be restricted to
	// only manifests with that type.
	//
	// FIXME(wuxler): is it possible to ask for multiple artifact types?
	Referrers(ctx context.Context, repo string, dgst digest.Digest, artifactType string) iter.Seq[v1.Descriptor]
}

Lister defines registry operations that enumerate objects within the registry. TODO(wuxler): support resumption from a given point.

type Pinger

type Pinger interface {
	// Ping checks if the storage is reachable.
	Ping(ctx context.Context) error
}

Pinger defines registry ping actions.

type Reader

type Reader interface {
	// GetManifest returns the contents of the manifest with the given digest.
	// The context also controls the lifetime of the returned ContentReadCloser.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrManifestUnknown when the blob is not present in the repository.
	GetManifest(ctx context.Context, repo string, dgst digest.Digest) (DescribableReadCloser, error)

	// GetTag returns the contents of the manifest with the given tag.
	// The context also controls the lifetime of the returned ContentReadCloser.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrManifestUnknown when the tag is not present in the repository.
	GetTag(ctx context.Context, repo string, tag string) (DescribableReadCloser, error)

	// StatManifest returns the descriptor for a given maniifest.
	// Only the MediaType, dgst and Size fields will be filled out.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrManifestUnknown when the blob is not present in the repository.
	StatManifest(ctx context.Context, repo string, dgst digest.Digest) (v1.Descriptor, error)

	// StatTag returns the descriptor for a given tag.
	// Only the MediaType, dgst and Size fields will be filled out.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrManifestUnknown when the blob is not present in the repository.
	StatTag(ctx context.Context, repo string, tag string) (v1.Descriptor, error)

	// StatBlob returns the descriptor for a given blob digest.
	// Only the MediaType, dgst and Size fields will be filled out.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrBlobUnknown when the blob is not present in the repository.
	StatBlob(ctx context.Context, repo string, dgst digest.Digest) (v1.Descriptor, error)

	// GetBlob returns the content of the blob with the given digest.
	// The context also controls the lifetime of the returned ContentReadCloser.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrBlobUnknown when the blob is not present in the repository.
	GetBlob(ctx context.Context, repo string, dgst digest.Digest) (DescribableReadCloser, error)

	// GetBlobRange is like GetBlob but asks to get only the given range of bytes from the blob,
	// starting at "start" offset, up to but not including "end" offset.
	// If "end" offset is negative or exceeds the actual size of the blob, GetBlobRange will
	// return all the data starting from "start" offset.
	// The context also controls the lifetime of the returned ContentReadCloser.
	GetBlobRange(ctx context.Context, repo string, dgst digest.Digest, start, end int64) (DescribableReadCloser, error)
}

Reader defines registry read actions for blobs, manifests, and other resources.

type RegistryClient

type RegistryClient struct {
	HTTPClient *Client
	// contains filtered or unexported fields
}

func (*RegistryClient) GetBlob

func (c *RegistryClient) GetBlob(ctx context.Context, repo string, dgst digest.Digest) (DescribableReadCloser, error)

GetBlob returns the content of the blob with the given digest. The context also controls the lifetime of the returned DescribableReadCloser.

func (*RegistryClient) GetBlobRange

func (c *RegistryClient) GetBlobRange(ctx context.Context, repo string, dgst digest.Digest, start, end int64) (DescribableReadCloser, error)

GetBlobRange is like GetBlob but asks to get only the given range of bytes from the blob, starting at "start" offset, up to but not including "end" offset. If "end" offset is negative or exceeds the actual size of the blob, GetBlobRange will return all the data starting from "start" offset. The context also controls the lifetime of the returned DescribableReadCloser.

func (*RegistryClient) GetManifest

func (c *RegistryClient) GetManifest(ctx context.Context, repo string, dgst digest.Digest) (DescribableReadCloser, error)

GetManifest returns the contents of the manifest with the given digest. The context also controls the lifetime of the returned DescribableReadCloser.

func (*RegistryClient) GetTag

func (c *RegistryClient) GetTag(ctx context.Context, repo string, tag string) (DescribableReadCloser, error)

GetTag returns the contents of the manifest with the given tag. The context also controls the lifetime of the returned DescribableReadCloser.

func (*RegistryClient) Ping

func (c *RegistryClient) Ping(ctx context.Context) error

Ping checks if the storage is reachable.

func (*RegistryClient) StatBlob

func (c *RegistryClient) StatBlob(ctx context.Context, repo string, dgst digest.Digest) (v1.Descriptor, error)

StatBlob returns the descriptor for a given blob digest. Only the MediaType, dgst and Size fields will be filled out.

func (*RegistryClient) StatManifest

func (c *RegistryClient) StatManifest(ctx context.Context, repo string, dgst digest.Digest) (v1.Descriptor, error)

StatManifest returns the descriptor for a given maniifest. Only the MediaType, dgst and Size fields will be filled out.

func (*RegistryClient) StatTag

func (c *RegistryClient) StatTag(ctx context.Context, repo string, tag string) (v1.Descriptor, error)

StatTag returns the descriptor for a given tag. Only the MediaType, dgst and Size fields will be filled out.

type RouteDescriptor

type RouteDescriptor struct {
	// ID is the unique identifier for the route endpoint api.
	ID string
	// Method is the HTTP method for the route endpoint api.
	Method string
	// PathPattern is the HTTP path pattern for the route endpoint api.
	PathPattern string
	// QueryParams is the list of query parameters for the route endpoint api.
	QueryParams map[string]string
	// SuccessCodes is the list of HTTP status codes that indicate success.
	SuccessCodes []int
	// FailureCodes is the list of HTTP status codes that indicate failure.
	FailureCodes []int
}

RouteDescriptor is a descriptor for a route endpoint api.

type TokenCache

type TokenCache = xcache.Cache[authn.Token]

TokenCache is the cache for the Token related to the registry and scopes.

type TokenOptions

type TokenOptions struct {
	// ClientID used in fetching OAuth2 token as a required field.
	// If empty, a default client ID is used.
	// Reference:
	// - https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token
	ClientID string

	// ForceAttemptOAuth2 controls whether to follow OAuth2 with password grant
	// instead the distribution spec when authenticating using username and
	// password.
	// References:
	// - https://docs.docker.com/registry/spec/auth/jwt/
	// - https://docs.docker.com/registry/spec/auth/oauth/
	ForceAttemptOAuth2 bool

	// OfflineToken controls whether to return a refresh token along with the bearer token.
	// A refresh token is capable of getting additional bearer tokens for the same subject
	// with different scopes. The refresh token does not have an expiration and should be
	// considered completely opaque to the client.
	// References:
	// - https://docs.docker.com/registry/spec/auth/token/
	OfflineToken bool
}

TokenOptions is the options for fetching token from remote.

type Writer

type Writer interface {
	// PushBlob pushes a blob described by desc to the given repository, reading content from r.
	// Only the desc.Digest and desc.Size fields are used.
	// It returns desc with Digest set to the canonical digest for the blob.
	//
	// Errors:
	// 	- ErrNameUnknown when the repository is not present.
	// 	- ErrNameInvalid when the repository name is not valid.
	// 	- ErrDigestInvalid when desc.Digest does not match the content.
	// 	- ErrSizeInvalid when desc.Size does not match the content length.
	PushBlob(ctx context.Context, repo string, desc v1.Descriptor, r io.Reader) (v1.Descriptor, error)

	// PushBlobChunked starts to push a blob to the given repository.
	// The returned [WriteCloser] can be used to stream the upload and resume on temporary errors.
	//
	// The chunkSize parameter provides a hint for the chunk size to use
	// when writing to the registry. If it's zero, a suitable default will be chosen.
	// It might be larger if the underlying registry requires that.
	//
	// The context remains active as long as the WriteCloser is around: if it's
	// canceled, it should cause any blocked WriteCloser operations to terminate.
	PushBlobChunked(ctx context.Context, repo string, chunkSize int) (BlobWriteCloser, error)

	// PushBlobChunkedResume resumes a previous push of a blob started with PushBlobChunked.
	// The id should be the value returned from [WriteCloser.ID] from the previous push.
	// and the offset should be the value returned from [WriteCloser.Size].
	//
	// The offset and chunkSize should similarly be obtained from the previous [WriteCloser]
	// via the [WriteCloser.Size] and [WriteCloser.ChunkSize] methods.
	// Alternatively, set offset to -1 to continue where the last write left off,
	// and to only use chunkSize as a hint like in PushBlobChunked.
	//
	// The context remains active as long as the WriteCloser is around: if it's
	// canceled, it should cause any blocked WriteCloser operations to terminate.
	PushBlobChunkedResume(ctx context.Context, repo, id string, offset int64, chunkSize int) (BlobWriteCloser, error)

	// MountBlob makes a blob with the given digest that's in fromRepo available
	// in toRepo and returns its canonical descriptor.
	//
	// This avoids the need to pull content down from fromRepo only to push it to r.
	//
	// Errors:
	// 	- ErrUnsupported (when the repository does not support mounts).
	//
	// TODO(wuxler): the mount endpoint doesn't return the size of the content,
	// so to return a correctly populated descriptor, a client will need to make
	// an extra HTTP call to find that out. For now, we'll just say that
	// the descriptor returned from MountBlob might have a zero Size.
	MountBlob(ctx context.Context, fromRepo, toRepo string, dgst digest.Digest) (v1.Descriptor, error)

	// PushManifest pushes a manifest with the given media type and contents.
	// If tag is non-empty, the tag with that name will be pointed at the manifest.
	//
	// It returns a descriptor suitable for accessing the manifest.
	PushManifest(ctx context.Context, repo string, tag string, contents []byte, mediaType string) (v1.Descriptor, error)
}

Writer defines registry write actions for blobs, manifests, and other resources.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL