mirror of https://github.com/docker/cli.git
Merge pull request #4552 from thaJeztah/update_engine
vendor: github.com/docker/docker 7abd7fa73965 (v25.0.0-dev)
This commit is contained in:
commit
25ce44280b
|
@ -133,7 +133,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
|
|||
// would "miss" a creation.
|
||||
started := make(chan struct{})
|
||||
eh := command.InitEventHandler()
|
||||
eh.Handle("create", func(e events.Message) {
|
||||
eh.Handle(events.ActionCreate, func(e events.Message) {
|
||||
if opts.all {
|
||||
s := NewStats(e.ID[:12])
|
||||
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])
|
||||
if cStats.add(s) {
|
||||
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 {
|
||||
cStats.remove(e.ID[:12])
|
||||
}
|
||||
|
|
|
@ -10,21 +10,21 @@ import (
|
|||
// EventHandler is abstract interface for user to customize
|
||||
// own handle functions of each type of events
|
||||
type EventHandler interface {
|
||||
Handle(action string, h func(events.Message))
|
||||
Handle(action events.Action, h func(events.Message))
|
||||
Watch(c <-chan events.Message)
|
||||
}
|
||||
|
||||
// InitEventHandler initializes and returns an 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 {
|
||||
handlers map[string]func(events.Message)
|
||||
handlers map[events.Action]func(events.Message)
|
||||
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.handlers[action] = h
|
||||
w.mu.Unlock()
|
||||
|
|
|
@ -17,9 +17,9 @@ import (
|
|||
|
||||
func TestEventsFormat(t *testing.T) {
|
||||
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{
|
||||
Status: action,
|
||||
Status: string(action),
|
||||
ID: "abc123",
|
||||
From: "ubuntu:latest",
|
||||
Type: events.ContainerEventType,
|
||||
|
|
|
@ -12,7 +12,7 @@ require (
|
|||
github.com/containerd/containerd v1.6.22
|
||||
github.com/creack/pty v1.1.18
|
||||
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/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
|
|
|
@ -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.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/docker v24.0.0-rc.2.0.20230828170219-a65c948e7edf+incompatible h1:kW2gtg0d8U36kbMoM7eqXIA7PuXGw3l/A3cxwdnbZPU=
|
||||
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 h1:i2QiMyOrwAI5M1Gg9U5jJJxx45b6YeqbDny9xwsUmv8=
|
||||
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/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
|
|
|
@ -8268,7 +8268,7 @@ paths:
|
|||
/images/create:
|
||||
post:
|
||||
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"
|
||||
consumes:
|
||||
- "text/plain"
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
dockerspec "github.com/docker/docker/image/spec/specs-go/v1"
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
|
@ -33,26 +34,7 @@ type StopOptions struct {
|
|||
}
|
||||
|
||||
// HealthConfig holds configuration settings for the HEALTHCHECK feature.
|
||||
type HealthConfig 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"`
|
||||
}
|
||||
type HealthConfig = dockerspec.HealthcheckConfig
|
||||
|
||||
// ExecStartOptions holds the options to start container's exec.
|
||||
type ExecStartOptions struct {
|
||||
|
|
|
@ -18,6 +18,86 @@ const (
|
|||
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,
|
||||
// like a container, or a network, or a volume.
|
||||
// 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.
|
||||
|
||||
Type Type
|
||||
Action string
|
||||
Action Action
|
||||
Actor Actor
|
||||
// Engine events are local scope. Cluster events are swarm scope.
|
||||
Scope string `json:"scope,omitempty"`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package errdefs // import "github.com/docker/docker/errdefs"
|
||||
package errdefs
|
||||
|
||||
// ErrNotFound signals that the requested object doesn't exist
|
||||
type ErrNotFound interface {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package errdefs // import "github.com/docker/docker/errdefs"
|
||||
package errdefs
|
||||
|
||||
import "context"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package errdefs // import "github.com/docker/docker/errdefs"
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package errdefs // import "github.com/docker/docker/errdefs"
|
||||
package errdefs
|
||||
|
||||
type causer interface {
|
||||
Cause() error
|
||||
|
|
|
@ -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"`
|
||||
}
|
|
@ -125,8 +125,10 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ConvertToHostname converts a registry url which has http|https prepended
|
||||
// to just an hostname.
|
||||
// ConvertToHostname normalizes a registry URL which has http|https prepended
|
||||
// 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 {
|
||||
stripped := url
|
||||
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
|
||||
// them to the new format and testing
|
||||
for registry, ac := range authConfigs {
|
||||
if configKey == ConvertToHostname(registry) {
|
||||
for registryURL, ac := range authConfigs {
|
||||
if configKey == ConvertToHostname(registryURL) {
|
||||
return ac
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,7 +320,8 @@ func isCIDRMatch(cidrs []*registry.NetIPNet, URLHost string) bool {
|
|||
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) {
|
||||
uri, err := url.Parse(val)
|
||||
if err != nil {
|
||||
|
@ -340,7 +341,8 @@ func ValidateMirror(val string) (string, error) {
|
|||
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) {
|
||||
// TODO: upstream this to check to reference package
|
||||
if val == "index.docker.io" {
|
||||
|
@ -426,19 +428,10 @@ func newRepositoryInfo(config *serviceConfig, name reference.Named) (*Repository
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ParseRepositoryInfo performs the breakdown of a repository name into a RepositoryInfo, but
|
||||
// lacks registry configuration.
|
||||
// ParseRepositoryInfo performs the breakdown of a repository name into a
|
||||
// [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) {
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -113,51 +113,6 @@ func Headers(userAgent string, metaHeaders http.Header) []transport.RequestModif
|
|||
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
|
||||
// default TLS configuration.
|
||||
func newTransport(tlsConfig *tls.Config) *http.Transport {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package registry // import "github.com/docker/docker/registry"
|
||||
package registry
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@ -6,12 +6,11 @@ import (
|
|||
"strconv"
|
||||
"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/registry"
|
||||
"github.com/docker/docker/errdefs"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
|
|
@ -82,23 +82,14 @@ func validateEndpoint(endpoint *v1Endpoint) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// trimV1Address trims the version off the address and returns the
|
||||
// trimmed address or an error if there is a non-V1 version.
|
||||
// trimV1Address trims the "v1" version suffix off the address and returns
|
||||
// the trimmed address. It returns an error on "v2" endpoints.
|
||||
func trimV1Address(address string) (string, error) {
|
||||
address = strings.TrimSuffix(address, "/")
|
||||
chunks := strings.Split(address, "/")
|
||||
apiVersionStr := chunks[len(chunks)-1]
|
||||
if apiVersionStr == "v1" {
|
||||
return strings.Join(chunks[:len(chunks)-1], "/"), nil
|
||||
trimmed := strings.TrimSuffix(address, "/")
|
||||
if strings.HasSuffix(trimmed, "/v2") {
|
||||
return "", invalidParamf("search is not supported on v2 endpoints: %s", address)
|
||||
}
|
||||
|
||||
for k, v := range apiVersions {
|
||||
if k != APIVersion1 && apiVersionStr == v {
|
||||
return "", invalidParamf("unsupported V1 version path %s", apiVersionStr)
|
||||
}
|
||||
}
|
||||
|
||||
return address, nil
|
||||
return strings.TrimSuffix(trimmed, "/v1"), nil
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
}
|
|
@ -20,8 +20,8 @@ type Service struct {
|
|||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewService returns a new instance of defaultService ready to be
|
||||
// installed into an engine.
|
||||
// NewService returns a new instance of [Service] ready to be installed into
|
||||
// an engine.
|
||||
func NewService(options ServiceOptions) (*Service, error) {
|
||||
config, err := newServiceConfig(options)
|
||||
|
||||
|
@ -91,18 +91,6 @@ func (s *Service) Auth(ctx context.Context, authConfig *registry.AuthConfig, use
|
|||
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
|
||||
// and configuration of the associated registry.
|
||||
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 {
|
||||
Mirror bool
|
||||
URL *url.URL
|
||||
Version APIVersion
|
||||
Version APIVersion // Deprecated: v1 registries are deprecated, and endpoints are always v2.
|
||||
AllowNondistributableArtifacts bool
|
||||
Official bool
|
||||
TrimHostname bool
|
||||
|
|
|
@ -25,7 +25,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
|
|||
}
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: mirrorURL,
|
||||
Version: APIVersion2,
|
||||
Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
|
||||
Mirror: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: mirrorTLSConfig,
|
||||
|
@ -33,7 +33,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
|
|||
}
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: DefaultV2Registry,
|
||||
Version: APIVersion2,
|
||||
Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
|
||||
Official: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsconfig.ServerDefault(),
|
||||
|
@ -55,7 +55,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
|
|||
Scheme: "https",
|
||||
Host: hostname,
|
||||
},
|
||||
Version: APIVersion2,
|
||||
Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
|
||||
AllowNondistributableArtifacts: ana,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
|
@ -68,7 +68,7 @@ func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, e
|
|||
Scheme: "http",
|
||||
Host: hostname,
|
||||
},
|
||||
Version: APIVersion2,
|
||||
Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition.
|
||||
AllowNondistributableArtifacts: ana,
|
||||
TrimHostname: true,
|
||||
// used to check if supposed to be secure via InsecureSkipVerify
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
|
||||
// APIVersion is an integral representation of an API version (presently
|
||||
// either 1 or 2)
|
||||
//
|
||||
// Deprecated: v1 registries are deprecated, and endpoints are always v2.
|
||||
type APIVersion int
|
||||
|
||||
func (av APIVersion) String() string {
|
||||
|
@ -15,8 +17,8 @@ func (av APIVersion) String() string {
|
|||
|
||||
// API Version identifiers.
|
||||
const (
|
||||
APIVersion1 APIVersion = 1
|
||||
APIVersion2 APIVersion = 2
|
||||
APIVersion1 APIVersion = 1 // Deprecated: v1 registries are deprecated, and endpoints are always v2.
|
||||
APIVersion2 APIVersion = 2 // Deprecated: v1 registries are deprecated, and endpoints are always v2.
|
||||
)
|
||||
|
||||
var apiVersions = map[APIVersion]string{
|
||||
|
|
|
@ -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/memory
|
||||
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
|
||||
github.com/docker/docker/api
|
||||
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/client
|
||||
github.com/docker/docker/errdefs
|
||||
github.com/docker/docker/image/spec/specs-go/v1
|
||||
github.com/docker/docker/internal/multierror
|
||||
github.com/docker/docker/pkg/archive
|
||||
github.com/docker/docker/pkg/homedir
|
||||
|
|
Loading…
Reference in New Issue