Merge pull request #4552 from thaJeztah/update_engine

vendor: github.com/docker/docker 7abd7fa73965 (v25.0.0-dev)
This commit is contained in:
Sebastiaan van Stijn 2023-09-05 17:32:58 +02:00 committed by GitHub
commit 25ce44280b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 258 additions and 143 deletions

View File

@ -133,7 +133,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
// would "miss" a creation. // would "miss" a creation.
started := make(chan struct{}) started := make(chan struct{})
eh := command.InitEventHandler() eh := command.InitEventHandler()
eh.Handle("create", func(e events.Message) { eh.Handle(events.ActionCreate, func(e events.Message) {
if opts.all { if opts.all {
s := NewStats(e.ID[:12]) s := NewStats(e.ID[:12])
if cStats.add(s) { if cStats.add(s) {
@ -143,7 +143,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
} }
}) })
eh.Handle("start", func(e events.Message) { eh.Handle(events.ActionStart, func(e events.Message) {
s := NewStats(e.ID[:12]) s := NewStats(e.ID[:12])
if cStats.add(s) { if cStats.add(s) {
waitFirst.Add(1) waitFirst.Add(1)
@ -151,7 +151,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
} }
}) })
eh.Handle("die", func(e events.Message) { eh.Handle(events.ActionDie, func(e events.Message) {
if !opts.all { if !opts.all {
cStats.remove(e.ID[:12]) cStats.remove(e.ID[:12])
} }

View File

@ -10,21 +10,21 @@ import (
// EventHandler is abstract interface for user to customize // EventHandler is abstract interface for user to customize
// own handle functions of each type of events // own handle functions of each type of events
type EventHandler interface { type EventHandler interface {
Handle(action string, h func(events.Message)) Handle(action events.Action, h func(events.Message))
Watch(c <-chan events.Message) Watch(c <-chan events.Message)
} }
// InitEventHandler initializes and returns an EventHandler // InitEventHandler initializes and returns an EventHandler
func InitEventHandler() EventHandler { func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[string]func(events.Message))} return &eventHandler{handlers: make(map[events.Action]func(events.Message))}
} }
type eventHandler struct { type eventHandler struct {
handlers map[string]func(events.Message) handlers map[events.Action]func(events.Message)
mu sync.Mutex mu sync.Mutex
} }
func (w *eventHandler) Handle(action string, h func(events.Message)) { func (w *eventHandler) Handle(action events.Action, h func(events.Message)) {
w.mu.Lock() w.mu.Lock()
w.handlers[action] = h w.handlers[action] = h
w.mu.Unlock() w.mu.Unlock()

View File

@ -17,9 +17,9 @@ import (
func TestEventsFormat(t *testing.T) { func TestEventsFormat(t *testing.T) {
var evts []events.Message var evts []events.Message
for i, action := range []string{"create", "start", "attach", "die"} { for i, action := range []events.Action{events.ActionCreate, events.ActionStart, events.ActionAttach, events.ActionDie} {
evts = append(evts, events.Message{ evts = append(evts, events.Message{
Status: action, Status: string(action),
ID: "abc123", ID: "abc123",
From: "ubuntu:latest", From: "ubuntu:latest",
Type: events.ContainerEventType, Type: events.ContainerEventType,

View File

@ -12,7 +12,7 @@ require (
github.com/containerd/containerd v1.6.22 github.com/containerd/containerd v1.6.22
github.com/creack/pty v1.1.18 github.com/creack/pty v1.1.18
github.com/docker/distribution v2.8.2+incompatible github.com/docker/distribution v2.8.2+incompatible
github.com/docker/docker v24.0.0-rc.2.0.20230828170219-a65c948e7edf+incompatible // master (v25.0.0-dev) github.com/docker/docker v24.0.0-rc.2.0.20230905102234-7abd7fa73965+incompatible // master (v25.0.0-dev)
github.com/docker/docker-credential-helpers v0.8.0 github.com/docker/docker-credential-helpers v0.8.0
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0

View File

@ -50,8 +50,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xb
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.0-rc.2.0.20230828170219-a65c948e7edf+incompatible h1:kW2gtg0d8U36kbMoM7eqXIA7PuXGw3l/A3cxwdnbZPU= github.com/docker/docker v24.0.0-rc.2.0.20230905102234-7abd7fa73965+incompatible h1:i2QiMyOrwAI5M1Gg9U5jJJxx45b6YeqbDny9xwsUmv8=
github.com/docker/docker v24.0.0-rc.2.0.20230828170219-a65c948e7edf+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.0-rc.2.0.20230905102234-7abd7fa73965+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=

View File

@ -8268,7 +8268,7 @@ paths:
/images/create: /images/create:
post: post:
summary: "Create an image" summary: "Create an image"
description: "Create an image by either pulling it from a registry or importing it." description: "Pull or import an image."
operationId: "ImageCreate" operationId: "ImageCreate"
consumes: consumes:
- "text/plain" - "text/plain"

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/docker/docker/api/types/strslice" "github.com/docker/docker/api/types/strslice"
dockerspec "github.com/docker/docker/image/spec/specs-go/v1"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
) )
@ -33,26 +34,7 @@ type StopOptions struct {
} }
// HealthConfig holds configuration settings for the HEALTHCHECK feature. // HealthConfig holds configuration settings for the HEALTHCHECK feature.
type HealthConfig struct { type HealthConfig = dockerspec.HealthcheckConfig
// Test is the test to perform to check that the container is healthy.
// An empty slice means to inherit the default.
// The options are:
// {} : inherit healthcheck
// {"NONE"} : disable healthcheck
// {"CMD", args...} : exec arguments directly
// {"CMD-SHELL", command} : run command with system's default shell
Test []string `json:",omitempty"`
// Zero means to inherit. Durations are expressed as integer nanoseconds.
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
StartInterval time.Duration `json:",omitempty"` // The interval to attempt healthchecks at during the start period
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
// Zero means inherit.
Retries int `json:",omitempty"`
}
// ExecStartOptions holds the options to start container's exec. // ExecStartOptions holds the options to start container's exec.
type ExecStartOptions struct { type ExecStartOptions struct {

View File

@ -18,6 +18,86 @@ const (
VolumeEventType Type = "volume" // VolumeEventType is the event type that volumes generate. VolumeEventType Type = "volume" // VolumeEventType is the event type that volumes generate.
) )
// Action is used for event-actions.
type Action string
const (
ActionCreate Action = "create"
ActionStart Action = "start"
ActionRestart Action = "restart"
ActionStop Action = "stop"
ActionCheckpoint Action = "checkpoint"
ActionPause Action = "pause"
ActionUnPause Action = "unpause"
ActionAttach Action = "attach"
ActionDetach Action = "detach"
ActionResize Action = "resize"
ActionUpdate Action = "update"
ActionRename Action = "rename"
ActionKill Action = "kill"
ActionDie Action = "die"
ActionOOM Action = "oom"
ActionDestroy Action = "destroy"
ActionRemove Action = "remove"
ActionCommit Action = "commit"
ActionTop Action = "top"
ActionCopy Action = "copy"
ActionArchivePath Action = "archive-path"
ActionExtractToDir Action = "extract-to-dir"
ActionExport Action = "export"
ActionImport Action = "import"
ActionSave Action = "save"
ActionLoad Action = "load"
ActionTag Action = "tag"
ActionUnTag Action = "untag"
ActionPush Action = "push"
ActionPull Action = "pull"
ActionPrune Action = "prune"
ActionDelete Action = "delete"
ActionEnable Action = "enable"
ActionDisable Action = "disable"
ActionConnect Action = "connect"
ActionDisconnect Action = "disconnect"
ActionReload Action = "reload"
ActionMount Action = "mount"
ActionUnmount Action = "unmount"
// ActionExecCreate is the prefix used for exec_create events. These
// event-actions are commonly followed by a colon and space (": "),
// and the command that's defined for the exec, for example:
//
// exec_create: /bin/sh -c 'echo hello'
//
// This is far from ideal; it's a compromise to allow filtering and
// to preserve backward-compatibility.
ActionExecCreate Action = "exec_create"
// ActionExecStart is the prefix used for exec_create events. These
// event-actions are commonly followed by a colon and space (": "),
// and the command that's defined for the exec, for example:
//
// exec_start: /bin/sh -c 'echo hello'
//
// This is far from ideal; it's a compromise to allow filtering and
// to preserve backward-compatibility.
ActionExecStart Action = "exec_start"
ActionExecDie Action = "exec_die"
ActionExecDetach Action = "exec_detach"
// ActionHealthStatus is the prefix to use for health_status events.
//
// Health-status events can either have a pre-defined status, in which
// case the "health_status" action is followed by a colon, or can be
// "free-form", in which case they're followed by the output of the
// health-check output.
//
// This is far form ideal, and a compromise to allow filtering, and
// to preserve backward-compatibility.
ActionHealthStatus Action = "health_status"
ActionHealthStatusRunning Action = "health_status: running"
ActionHealthStatusHealthy Action = "health_status: healthy"
ActionHealthStatusUnhealthy Action = "health_status: unhealthy"
)
// Actor describes something that generates events, // Actor describes something that generates events,
// like a container, or a network, or a volume. // like a container, or a network, or a volume.
// It has a defined name and a set of attributes. // It has a defined name and a set of attributes.
@ -37,7 +117,7 @@ type Message struct {
From string `json:"from,omitempty"` // Deprecated: use Actor.Attributes["image"] instead. From string `json:"from,omitempty"` // Deprecated: use Actor.Attributes["image"] instead.
Type Type Type Type
Action string Action Action
Actor Actor Actor Actor
// Engine events are local scope. Cluster events are swarm scope. // Engine events are local scope. Cluster events are swarm scope.
Scope string `json:"scope,omitempty"` Scope string `json:"scope,omitempty"`

View File

@ -1,4 +1,4 @@
package errdefs // import "github.com/docker/docker/errdefs" package errdefs
// ErrNotFound signals that the requested object doesn't exist // ErrNotFound signals that the requested object doesn't exist
type ErrNotFound interface { type ErrNotFound interface {

View File

@ -1,4 +1,4 @@
package errdefs // import "github.com/docker/docker/errdefs" package errdefs
import "context" import "context"

View File

@ -1,4 +1,4 @@
package errdefs // import "github.com/docker/docker/errdefs" package errdefs
import ( import (
"net/http" "net/http"

View File

@ -1,4 +1,4 @@
package errdefs // import "github.com/docker/docker/errdefs" package errdefs
type causer interface { type causer interface {
Cause() error Cause() error

View File

@ -0,0 +1,54 @@
package v1
import (
"time"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
const DockerOCIImageMediaType = "application/vnd.docker.container.image.v1+json"
// DockerOCIImage is a ocispec.Image extended with Docker specific Config.
type DockerOCIImage struct {
ocispec.Image
// Shadow ocispec.Image.Config
Config DockerOCIImageConfig `json:"config,omitempty"`
}
// DockerOCIImageConfig is a ocispec.ImageConfig extended with Docker specific fields.
type DockerOCIImageConfig struct {
ocispec.ImageConfig
DockerOCIImageConfigExt
}
// DockerOCIImageConfigExt contains Docker-specific fields in DockerImageConfig.
type DockerOCIImageConfigExt struct {
Healthcheck *HealthcheckConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
OnBuild []string `json:",omitempty"` // ONBUILD metadata that were defined on the image Dockerfile
Shell []string `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
}
// HealthcheckConfig holds configuration settings for the HEALTHCHECK feature.
type HealthcheckConfig struct {
// Test is the test to perform to check that the container is healthy.
// An empty slice means to inherit the default.
// The options are:
// {} : inherit healthcheck
// {"NONE"} : disable healthcheck
// {"CMD", args...} : exec arguments directly
// {"CMD-SHELL", command} : run command with system's default shell
Test []string `json:",omitempty"`
// Zero means to inherit. Durations are expressed as integer nanoseconds.
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
StartInterval time.Duration `json:",omitempty"` // The interval to attempt healthchecks at during the start period
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
// Zero means inherit.
Retries int `json:",omitempty"`
}

View File

@ -125,8 +125,10 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi
}, nil }, nil
} }
// ConvertToHostname converts a registry url which has http|https prepended // ConvertToHostname normalizes a registry URL which has http|https prepended
// to just an hostname. // to just its hostname. It is used to match credentials, which may be either
// stored as hostname or as hostname including scheme (in legacy configuration
// files).
func ConvertToHostname(url string) string { func ConvertToHostname(url string) string {
stripped := url stripped := url
if strings.HasPrefix(url, "http://") { if strings.HasPrefix(url, "http://") {
@ -147,8 +149,8 @@ func ResolveAuthConfig(authConfigs map[string]registry.AuthConfig, index *regist
// Maybe they have a legacy config file, we will iterate the keys converting // Maybe they have a legacy config file, we will iterate the keys converting
// them to the new format and testing // them to the new format and testing
for registry, ac := range authConfigs { for registryURL, ac := range authConfigs {
if configKey == ConvertToHostname(registry) { if configKey == ConvertToHostname(registryURL) {
return ac return ac
} }
} }

View File

@ -320,7 +320,8 @@ func isCIDRMatch(cidrs []*registry.NetIPNet, URLHost string) bool {
return false return false
} }
// ValidateMirror validates an HTTP(S) registry mirror // ValidateMirror validates an HTTP(S) registry mirror. It is used by the daemon
// to validate the daemon configuration.
func ValidateMirror(val string) (string, error) { func ValidateMirror(val string) (string, error) {
uri, err := url.Parse(val) uri, err := url.Parse(val)
if err != nil { if err != nil {
@ -340,7 +341,8 @@ func ValidateMirror(val string) (string, error) {
return strings.TrimSuffix(val, "/") + "/", nil return strings.TrimSuffix(val, "/") + "/", nil
} }
// ValidateIndexName validates an index name. // ValidateIndexName validates an index name. It is used by the daemon to
// validate the daemon configuration.
func ValidateIndexName(val string) (string, error) { func ValidateIndexName(val string) (string, error) {
// TODO: upstream this to check to reference package // TODO: upstream this to check to reference package
if val == "index.docker.io" { if val == "index.docker.io" {
@ -426,19 +428,10 @@ func newRepositoryInfo(config *serviceConfig, name reference.Named) (*Repository
}, nil }, nil
} }
// ParseRepositoryInfo performs the breakdown of a repository name into a RepositoryInfo, but // ParseRepositoryInfo performs the breakdown of a repository name into a
// lacks registry configuration. // [RepositoryInfo], but lacks registry configuration.
//
// It is used by the Docker cli to interact with registry-related endpoints.
func ParseRepositoryInfo(reposName reference.Named) (*RepositoryInfo, error) { func ParseRepositoryInfo(reposName reference.Named) (*RepositoryInfo, error) {
return newRepositoryInfo(emptyServiceConfig, reposName) return newRepositoryInfo(emptyServiceConfig, reposName)
} }
// ParseSearchIndexInfo will use repository name to get back an indexInfo.
//
// TODO(thaJeztah) this function is only used by the CLI, and used to get
// information of the registry (to provide credentials if needed). We should
// move this function (or equivalent) to the CLI, as it's doing too much just
// for that.
func ParseSearchIndexInfo(reposName string) (*registry.IndexInfo, error) {
indexName, _ := splitReposSearchTerm(reposName)
return newIndexInfo(emptyServiceConfig, indexName)
}

View File

@ -113,51 +113,6 @@ func Headers(userAgent string, metaHeaders http.Header) []transport.RequestModif
return modifiers return modifiers
} }
// httpClient returns an HTTP client structure which uses the given transport
// and contains the necessary headers for redirected requests
func httpClient(transport http.RoundTripper) *http.Client {
return &http.Client{
Transport: transport,
CheckRedirect: addRequiredHeadersToRedirectedRequests,
}
}
func trustedLocation(req *http.Request) bool {
var (
trusteds = []string{"docker.com", "docker.io"}
hostname = strings.SplitN(req.Host, ":", 2)[0]
)
if req.URL.Scheme != "https" {
return false
}
for _, trusted := range trusteds {
if hostname == trusted || strings.HasSuffix(hostname, "."+trusted) {
return true
}
}
return false
}
// addRequiredHeadersToRedirectedRequests adds the necessary redirection headers
// for redirected requests
func addRequiredHeadersToRedirectedRequests(req *http.Request, via []*http.Request) error {
if len(via) != 0 && via[0] != nil {
if trustedLocation(req) && trustedLocation(via[0]) {
req.Header = via[0].Header
return nil
}
for k, v := range via[0].Header {
if k != "Authorization" {
for _, vv := range v {
req.Header.Add(k, vv)
}
}
}
}
return nil
}
// newTransport returns a new HTTP transport. If tlsConfig is nil, it uses the // newTransport returns a new HTTP transport. If tlsConfig is nil, it uses the
// default TLS configuration. // default TLS configuration.
func newTransport(tlsConfig *tls.Config) *http.Transport { func newTransport(tlsConfig *tls.Config) *http.Transport {

View File

@ -1,4 +1,4 @@
package registry // import "github.com/docker/docker/registry" package registry
import ( import (
"context" "context"
@ -6,12 +6,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/containerd/containerd/log"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
"github.com/containerd/containerd/log"
"github.com/docker/distribution/registry/client/auth"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -139,3 +138,26 @@ func (s *Service) searchUnfiltered(ctx context.Context, term string, limit int,
return newSession(client, endpoint).searchRepositories(remoteName, limit) return newSession(client, endpoint).searchRepositories(remoteName, limit)
} }
// splitReposSearchTerm breaks a search term into an index name and remote name
func splitReposSearchTerm(reposName string) (string, string) {
nameParts := strings.SplitN(reposName, "/", 2)
if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") &&
!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
// This is a Docker Hub repository (ex: samalba/hipache or ubuntu),
// use the default Docker Hub registry (docker.io)
return IndexName, reposName
}
return nameParts[0], nameParts[1]
}
// ParseSearchIndexInfo will use repository name to get back an indexInfo.
//
// TODO(thaJeztah) this function is only used by the CLI, and used to get
// information of the registry (to provide credentials if needed). We should
// move this function (or equivalent) to the CLI, as it's doing too much just
// for that.
func ParseSearchIndexInfo(reposName string) (*registry.IndexInfo, error) {
indexName, _ := splitReposSearchTerm(reposName)
return newIndexInfo(emptyServiceConfig, indexName)
}

View File

@ -82,23 +82,14 @@ func validateEndpoint(endpoint *v1Endpoint) error {
return nil return nil
} }
// trimV1Address trims the version off the address and returns the // trimV1Address trims the "v1" version suffix off the address and returns
// trimmed address or an error if there is a non-V1 version. // the trimmed address. It returns an error on "v2" endpoints.
func trimV1Address(address string) (string, error) { func trimV1Address(address string) (string, error) {
address = strings.TrimSuffix(address, "/") trimmed := strings.TrimSuffix(address, "/")
chunks := strings.Split(address, "/") if strings.HasSuffix(trimmed, "/v2") {
apiVersionStr := chunks[len(chunks)-1] return "", invalidParamf("search is not supported on v2 endpoints: %s", address)
if apiVersionStr == "v1" {
return strings.Join(chunks[:len(chunks)-1], "/"), nil
} }
return strings.TrimSuffix(trimmed, "/v1"), nil
for k, v := range apiVersions {
if k != APIVersion1 && apiVersionStr == v {
return "", invalidParamf("unsupported V1 version path %s", apiVersionStr)
}
}
return address, nil
} }
func newV1EndpointFromStr(address string, tlsConfig *tls.Config, headers http.Header) (*v1Endpoint, error) { func newV1EndpointFromStr(address string, tlsConfig *tls.Config, headers http.Header) (*v1Endpoint, error) {
@ -184,3 +175,48 @@ func (e *v1Endpoint) ping() (v1PingResult, error) {
log.G(context.TODO()).Debugf("v1PingResult.Standalone: %t", info.Standalone) log.G(context.TODO()).Debugf("v1PingResult.Standalone: %t", info.Standalone)
return info, nil return info, nil
} }
// httpClient returns an HTTP client structure which uses the given transport
// and contains the necessary headers for redirected requests
func httpClient(transport http.RoundTripper) *http.Client {
return &http.Client{
Transport: transport,
CheckRedirect: addRequiredHeadersToRedirectedRequests,
}
}
func trustedLocation(req *http.Request) bool {
var (
trusteds = []string{"docker.com", "docker.io"}
hostname = strings.SplitN(req.Host, ":", 2)[0]
)
if req.URL.Scheme != "https" {
return false
}
for _, trusted := range trusteds {
if hostname == trusted || strings.HasSuffix(hostname, "."+trusted) {
return true
}
}
return false
}
// addRequiredHeadersToRedirectedRequests adds the necessary redirection headers
// for redirected requests
func addRequiredHeadersToRedirectedRequests(req *http.Request, via []*http.Request) error {
if len(via) != 0 && via[0] != nil {
if trustedLocation(req) && trustedLocation(via[0]) {
req.Header = via[0].Header
return nil
}
for k, v := range via[0].Header {
if k != "Authorization" {
for _, vv := range v {
req.Header.Add(k, vv)
}
}
}
}
return nil
}

View File

@ -20,8 +20,8 @@ type Service struct {
mu sync.RWMutex mu sync.RWMutex
} }
// NewService returns a new instance of defaultService ready to be // NewService returns a new instance of [Service] ready to be installed into
// installed into an engine. // an engine.
func NewService(options ServiceOptions) (*Service, error) { func NewService(options ServiceOptions) (*Service, error) {
config, err := newServiceConfig(options) config, err := newServiceConfig(options)
@ -91,18 +91,6 @@ func (s *Service) Auth(ctx context.Context, authConfig *registry.AuthConfig, use
return "", "", err return "", "", err
} }
// splitReposSearchTerm breaks a search term into an index name and remote name
func splitReposSearchTerm(reposName string) (string, string) {
nameParts := strings.SplitN(reposName, "/", 2)
if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") &&
!strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") {
// This is a Docker Hub repository (ex: samalba/hipache or ubuntu),
// use the default Docker Hub registry (docker.io)
return IndexName, reposName
}
return nameParts[0], nameParts[1]
}
// ResolveRepository splits a repository name into its components // ResolveRepository splits a repository name into its components
// and configuration of the associated registry. // and configuration of the associated registry.
func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, error) { func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, error) {
@ -115,7 +103,7 @@ func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, erro
type APIEndpoint struct { type APIEndpoint struct {
Mirror bool Mirror bool
URL *url.URL URL *url.URL
Version APIVersion Version APIVersion // Deprecated: v1 registries are deprecated, and endpoints are always v2.
AllowNondistributableArtifacts bool AllowNondistributableArtifacts bool
Official bool Official bool
TrimHostname bool TrimHostname bool

View File

@ -25,7 +25,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
} }
endpoints = append(endpoints, APIEndpoint{ endpoints = append(endpoints, APIEndpoint{
URL: mirrorURL, URL: mirrorURL,
Version: APIVersion2, Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
Mirror: true, Mirror: true,
TrimHostname: true, TrimHostname: true,
TLSConfig: mirrorTLSConfig, TLSConfig: mirrorTLSConfig,
@ -33,7 +33,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
} }
endpoints = append(endpoints, APIEndpoint{ endpoints = append(endpoints, APIEndpoint{
URL: DefaultV2Registry, URL: DefaultV2Registry,
Version: APIVersion2, Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
Official: true, Official: true,
TrimHostname: true, TrimHostname: true,
TLSConfig: tlsconfig.ServerDefault(), TLSConfig: tlsconfig.ServerDefault(),
@ -55,7 +55,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
Scheme: "https", Scheme: "https",
Host: hostname, Host: hostname,
}, },
Version: APIVersion2, Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
AllowNondistributableArtifacts: ana, AllowNondistributableArtifacts: ana,
TrimHostname: true, TrimHostname: true,
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
@ -68,7 +68,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
Scheme: "http", Scheme: "http",
Host: hostname, Host: hostname,
}, },
Version: APIVersion2, Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
AllowNondistributableArtifacts: ana, AllowNondistributableArtifacts: ana,
TrimHostname: true, TrimHostname: true,
// used to check if supposed to be secure via InsecureSkipVerify // used to check if supposed to be secure via InsecureSkipVerify

View File

@ -7,6 +7,8 @@ import (
// APIVersion is an integral representation of an API version (presently // APIVersion is an integral representation of an API version (presently
// either 1 or 2) // either 1 or 2)
//
// Deprecated: v1 registries are deprecated, and endpoints are always v2.
type APIVersion int type APIVersion int
func (av APIVersion) String() string { func (av APIVersion) String() string {
@ -15,8 +17,8 @@ func (av APIVersion) String() string {
// API Version identifiers. // API Version identifiers.
const ( const (
APIVersion1 APIVersion = 1 APIVersion1 APIVersion = 1 // Deprecated: v1 registries are deprecated, and endpoints are always v2.
APIVersion2 APIVersion = 2 APIVersion2 APIVersion = 2 // Deprecated: v1 registries are deprecated, and endpoints are always v2.
) )
var apiVersions = map[APIVersion]string{ var apiVersions = map[APIVersion]string{

3
vendor/modules.txt vendored
View File

@ -49,7 +49,7 @@ github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory github.com/docker/distribution/registry/storage/cache/memory
github.com/docker/distribution/uuid github.com/docker/distribution/uuid
# github.com/docker/docker v24.0.0-rc.2.0.20230828170219-a65c948e7edf+incompatible # github.com/docker/docker v24.0.0-rc.2.0.20230905102234-7abd7fa73965+incompatible
## explicit ## explicit
github.com/docker/docker/api github.com/docker/docker/api
github.com/docker/docker/api/types github.com/docker/docker/api/types
@ -73,6 +73,7 @@ github.com/docker/docker/builder/remotecontext/git
github.com/docker/docker/builder/remotecontext/urlutil github.com/docker/docker/builder/remotecontext/urlutil
github.com/docker/docker/client github.com/docker/docker/client
github.com/docker/docker/errdefs github.com/docker/docker/errdefs
github.com/docker/docker/image/spec/specs-go/v1
github.com/docker/docker/internal/multierror github.com/docker/docker/internal/multierror
github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/archive
github.com/docker/docker/pkg/homedir github.com/docker/docker/pkg/homedir