transport

package
v0.1.3-0...-0b0730e Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2020 License: Apache-2.0 Imports: 15 Imported by: 0

README

transport

GoDoc

The distribution protocol is fairly simple, but correctly implementing authentication is hard.

This package implements an http.RoundTripper that transparently performs:

for registry clients.

Raison d'être

Why not just use the docker/distribution client?

Great question! Mostly, because I don't want to depend on prometheus/client_golang.

As a performance optimization, that client uses a cache to keep track of a mapping between blob digests and their descriptors. Unfortunately, the cache uses prometheus to track hits and misses, so if you want to use that client you have to pull in all of prometheus, which is pretty large.

docker/distribution

Why does it matter if you depend on prometheus? Who cares?

It's generally polite to your downstream to reduce the number of dependencies your package requires:

  • Downloading your package is faster, which helps our Australian friends and people on airplanes.
  • There is less code to compile, which speeds up builds and saves the planet from global warming.
  • You reduce the likelihood of inflicting dependency hell upon your consumers.
  • Tim Hockin prefers it based on his experience working on Kubernetes, and he's a pretty smart guy.

Okay, what about containerd/containerd?

Similar reasons! That ends up pulling in grpc, protobuf, and logrus.

containerd/containerd

Well... what about containers/image?

That just uses the the docker/distribution client... and more!

containerd/containerd

Wow, what about this package?

Of course, this package isn't perfect either. transport depends on authn, which in turn depends on docker's config file parsing and handling package, which you don't strictly need but almost certainly want if you're going to be interacting with a registry.

google/go-containerregistry

These graphs were generated by kisielk/godepgraph.

Usage

This is heavily used by the remote package, which implements higher level image-centric functionality, but this package is useful if you want to interact directly with the registry to do something that remote doesn't support, e.g. to handle with schema 1 images.

This package also includes some error handling facilities in the form of CheckError, which will parse the response body into a structured error for unexpected http status codes.

Here's a "simple" program that writes the result of listing tags for gcr.io/google-containers/pause to stdout.

package main

import (
	"io"
	"net/http"
	"os"

	"github.com/google/go-containerregistry/pkg/authn"
	"github.com/google/go-containerregistry/pkg/name"
	"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)

func main() {
	repo, err := name.NewRepository("gcr.io/google-containers/pause")
	if err != nil {
		panic(err)
	}

	// Fetch credentials based on your docker config file, which is $HOME/.docker/config.json or $DOCKER_CONFIG.
	auth, err := authn.DefaultKeychain.Resolve(repo.Registry)
	if err != nil {
		panic(err)
	}

	// Construct an http.Client that is authorized to pull from gcr.io/google-containers/pause.
	scopes := []string{repo.Scope(transport.PullScope)}
	t, err := transport.New(repo.Registry, auth, http.DefaultTransport, scopes)
	if err != nil {
		panic(err)
	}
	client := &http.Client{Transport: t}

	// Make the actual request.
	resp, err := client.Get("https://gcr.io/v2/google-containers/pause/tags/list")
	if err != nil {
		panic(err)
	}

	// Assert that we get a 200, otherwise attempt to parse body as a structured error.
	if err := transport.CheckError(resp, http.StatusOK); err != nil {
		panic(err)
	}

	// Write the response to stdout.
	if _, err := io.Copy(os.Stdout, resp.Body); err != nil {
		panic(err)
	}
}

Documentation

Overview

Package transport provides facilities for setting up an authenticated http.RoundTripper given an Authenticator and base RoundTripper. See transport.New for more information.

Index

Constants

View Source
const (
	PullScope string = "pull"
	PushScope string = "push,pull"
	// For now DELETE is PUSH, which is the read/write ACL.
	DeleteScope  string = PushScope
	CatalogScope string = "catalog"
)

Scopes suitable to qualify each Repository

Variables

This section is empty.

Functions

func CheckError

func CheckError(resp *http.Response, codes ...int) error

CheckError returns a structured error if the response status is not in codes.

func New

New returns a new RoundTripper based on the provided RoundTripper that has been setup to authenticate with the remote registry "reg", in the capacity laid out by the specified scopes.

func NewLogger

func NewLogger(inner http.RoundTripper) http.RoundTripper

NewLogger returns a transport that logs requests and responses to github.com/google/go-containerregistry/pkg/logs.Debug.

func NewRetry

func NewRetry(inner http.RoundTripper, opts ...Option) http.RoundTripper

NewRetry returns a transport that retries errors.

Types

type Diagnostic

type Diagnostic struct {
	Code    ErrorCode   `json:"code"`
	Message string      `json:"message,omitempty"`
	Detail  interface{} `json:"detail,omitempty"`
}

Diagnostic represents a single error returned by a Docker registry interaction.

func (Diagnostic) String

func (d Diagnostic) String() string

String stringifies the Diagnostic in the form: $Code: $Message[; $Detail]

type Error

type Error struct {
	Errors []Diagnostic `json:"errors,omitempty"`
	// The http status code returned.
	StatusCode int
	// contains filtered or unexported fields
}

Error implements error to support the following error specification: https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors

func (*Error) Error

func (e *Error) Error() string

Error implements error

func (*Error) Temporary

func (e *Error) Temporary() bool

Temporary returns whether the request that preceded the error is temporary.

type ErrorCode

type ErrorCode string

ErrorCode is an enumeration of supported error codes.

const (
	BlobUnknownErrorCode         ErrorCode = "BLOB_UNKNOWN"
	BlobUploadInvalidErrorCode   ErrorCode = "BLOB_UPLOAD_INVALID"
	BlobUploadUnknownErrorCode   ErrorCode = "BLOB_UPLOAD_UNKNOWN"
	DigestInvalidErrorCode       ErrorCode = "DIGEST_INVALID"
	ManifestBlobUnknownErrorCode ErrorCode = "MANIFEST_BLOB_UNKNOWN"
	ManifestInvalidErrorCode     ErrorCode = "MANIFEST_INVALID"
	ManifestUnknownErrorCode     ErrorCode = "MANIFEST_UNKNOWN"
	ManifestUnverifiedErrorCode  ErrorCode = "MANIFEST_UNVERIFIED"
	NameInvalidErrorCode         ErrorCode = "NAME_INVALID"
	NameUnknownErrorCode         ErrorCode = "NAME_UNKNOWN"
	SizeInvalidErrorCode         ErrorCode = "SIZE_INVALID"
	TagInvalidErrorCode          ErrorCode = "TAG_INVALID"
	UnauthorizedErrorCode        ErrorCode = "UNAUTHORIZED"
	DeniedErrorCode              ErrorCode = "DENIED"
	UnsupportedErrorCode         ErrorCode = "UNSUPPORTED"
	TooManyRequestsErrorCode     ErrorCode = "TOOMANYREQUESTS"
)

The set of error conditions a registry may return: https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors-2

type Option

type Option func(*Options)

Option is a functional option for retryTransport.

func WithRetryBackoff

func WithRetryBackoff(backoff retry.Backoff) Option

WithRetryBackoff sets the backoff for retry operations.

func WithRetryPredicate

func WithRetryPredicate(predicate func(error) bool) Option

WithRetryPredicate sets the predicate for retry operations.

type Options

type Options struct {
	Backoff   retry.Backoff
	Predicate retry.Predicate
}

Jump to

Keyboard shortcuts

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