Compare commits

...

47 Commits

Author SHA1 Message Date
30df2d0b3a fix(loader): Allows multiple protocols on one port
Some checks failed
build / prepare (push) Has been cancelled
build / bin-image (push) Has been cancelled
build / prepare-plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / tests (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 25, local) (push) Has been cancelled
e2e / tests (alpine, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 27, local) (push) Has been cancelled
e2e / tests (alpine, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 28, local) (push) Has been cancelled
e2e / tests (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 25, local) (push) Has been cancelled
e2e / tests (debian, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 27, local) (push) Has been cancelled
e2e / tests (debian, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 28, local) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-14) (push) Has been cancelled
test / host (macos-15) (push) Has been cancelled
test / host (macos-15-intel) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
build / build (push) Has been cancelled
build / plugins (push) Has been cancelled
2026-02-02 12:28:16 +01:00
ecc694264d Merge pull request #6621 from thaJeztah/28.x_plugin_hide
Some checks failed
build / prepare (push) Has been cancelled
build / build (push) Has been cancelled
build / bin-image (push) Has been cancelled
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / tests (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 25, local) (push) Has been cancelled
e2e / tests (alpine, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 27, local) (push) Has been cancelled
e2e / tests (alpine, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 28, local) (push) Has been cancelled
e2e / tests (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 25, local) (push) Has been cancelled
e2e / tests (debian, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 27, local) (push) Has been cancelled
e2e / tests (debian, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 28, local) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-14) (push) Has been cancelled
test / host (macos-15) (push) Has been cancelled
test / host (macos-15-intel) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[28.x backport] Plugin may set itself as hidden
2025-11-05 11:32:31 +01:00
c475c696cf Plugin may set itself as hidden
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
(cherry picked from commit 700875b666)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-05 07:33:23 +01:00
7494d2cee4 cli: allManagementSubCommands: improve handling of plugin stubs
The allManagementSubCommands function is used to present plugin-commands
in the docker --help output; these commands are included in the "management
commands" section, but for plugins we don't know if they have sub-commands.

However, plugin stubs may be hidden (for placeholders that are not yet loaded),
or not be runnable, which was previously ignored.

This patch treats plugin-stubs the same as other commands, with the exception
of checking if they have subcommands (which is not yet known for plugin-stubs).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 259df25a96)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-05 07:33:08 +01:00
5306df36fa Merge pull request #6610 from thaJeztah/28.x_backport_deprecate_builder_utils
[28.x backport] cli/command/image/build: deprecate `DefaultDockerfileName`, `DetectArchiveReader`, `WriteTempDockerfile`, `ResolveAndValidateContextPath`
2025-11-04 07:23:51 -06:00
5dbaa52325 cli/command/image/build: deprecate ResolveAndValidateContextPath util
This utility was used internally and will be removed in the next release.
Use `DetectContextType` to detect the context-type, and use `GetContextFromLocalDir`,
`GetContextFromLocalDir`, `GetContextFromGitURL`, or `GetContextFromURL`
instead.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 0f2f9e9c41)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-04 07:14:44 -06:00
dd832b6d97 cli/command/image/build: deprecate WriteTempDockerfile util
It was only used internal in the package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 6e1ff0bec1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-04 07:14:44 -06:00
a99e91cc89 cli/command/image/build: deprecate DetectArchiveReader util
It was only used internal in the package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c52fa073cd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-04 07:14:44 -06:00
579b72aa06 cli/command/image/build: deprecate DefaultDockerfileName const
It was only used internal in the package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f24bb4bc76)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-04 07:14:40 -06:00
6fc5891770 Merge pull request #6560 from thaJeztah/28.x_backport_deprecations
[28.x backport] opts, image/build: deprecate IsArchive, ValidateMACAddress,  ListOpts.Delete()
2025-11-04 07:12:50 -06:00
9af6cbc489 Merge pull request #6613 from thaJeztah/28.x_bump_go
[28.x] update to go1.24.9
2025-11-04 06:45:14 -06:00
ba53322412 update to go1.24.9
go1.24.9 (released 2025-10-13) includes fixes to the crypto/x509 package.
See the Go 1.24.9 milestone on our issue tracker for details:

- https://github.com/golang/go/issues?q=milestone%3AGo1.24.9+label%3ACherryPickApproved
- full diff: https://github.com/golang/go/compare/go1.24.8...go1.24.9

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-04 11:10:08 +01:00
61d2e8aaad Merge pull request #6609 from thaJeztah/28.x_backport_bump_golangci_lint
[28.x backport] Dockerfile: update golangci-lint to v2.5.0
2025-11-03 11:39:06 -06:00
6abcd4a2a1 Merge pull request #6608 from thaJeztah/28.x_backport_update_gotestsum
[28.x backport] Dockerfile: bump gotest.tools/gotestsum v1.13.0
2025-11-03 15:41:42 +01:00
00c129b974 Merge pull request #6607 from thaJeztah/28.x_backport_update_actions
[28.x backport] update actions
2025-11-03 15:33:29 +01:00
fbf5c8a86d Dockerfile: update golangci-lint to v2.5.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5ad9fbdef7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-03 12:45:13 +01:00
4c7d52534f Dockerfile: bump gotest.tools/gotestsum v1.13.0
full diff: https://github.com/gotestyourself/gotestsum/compare/v1.12.3...v1.13.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f8b1b8d165)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-03 12:37:13 +01:00
70123c523c build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit aef2ef8c77)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-03 12:32:03 +01:00
4942b2747f build(deps): bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 5483b10e94)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-03 12:31:44 +01:00
d8bab71747 opts: deprecate ListOpts.Delete()
This method was added as part of a refactor in [moby@1ba1138], at which
time it was used to delete original values for "--host" and "--volume"
after normalizing. This beccame redundant in [moby@6200002], which added
specialized options that used a validate function, which both validated
and normalized inputs.

It's no longer used, so let's mark it deprecated so that we can remove it.

[moby@1ba1138]: 1ba11384bf
[moby@6200002]: 6200002669

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 193db8ec41)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-13 14:33:08 +02:00
36d9523e31 opts: deprecate ValidateMACAddress
It was a wrapper around net.ParseMAC from stdlib, so users should
use that directly.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 17d6a92954)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-13 14:30:34 +02:00
7063a0ef07 cli/command/image: runBuild: inline vars and minor cleanups
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9e646f6d92)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-13 14:26:53 +02:00
22487ad6f6 cli/command/image/build: deprecate IsArchive utility
It was only used internally.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 64be664e85)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-13 14:24:44 +02:00
4737ed4906 cli/command/image/build: fix linting, add sub-tests
- fix minor linting issues (unhandled errors)
- rename vars to prevent shadowing
- use sub-tests for tests that already prepared for it

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 2c539a6530)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-13 14:24:30 +02:00
8cff0087da Merge pull request #6544 from thaJeztah/28.x_bump_engine
[28.x] vendor: github.com/docker/docker v28.5.1
2025-10-09 10:11:06 +02:00
e8b22ce03c vendor: github.com/docker/docker v28.5.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-08 16:17:13 +02:00
e180ab8ab8 Merge pull request #6541 from vvoland/6540-28.x
Some checks failed
build / prepare (push) Has been cancelled
build / build (push) Has been cancelled
build / bin-image (push) Has been cancelled
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / tests (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 25, local) (push) Has been cancelled
e2e / tests (alpine, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 27, local) (push) Has been cancelled
e2e / tests (alpine, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 28, local) (push) Has been cancelled
e2e / tests (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 25, local) (push) Has been cancelled
e2e / tests (debian, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 27, local) (push) Has been cancelled
e2e / tests (debian, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 28, local) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-14) (push) Has been cancelled
test / host (macos-15) (push) Has been cancelled
test / host (macos-15-intel) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[28.x backport] update to go1.24.8
2025-10-07 19:50:32 -07:00
0d799c556f update to go1.24.8
This minor release includes 10 security fixes following the security policy:

- net/mail: excessive CPU consumption in ParseAddress

    The ParseAddress function constructed domain-literal address components through repeated string concatenation. When parsing large domain-literal components, this could cause excessive CPU consumption.

    Thanks to Philippe Antoine (Catena cyber) for reporting this issue.

    This is CVE-2025-61725 and Go issue https://go.dev/issue/75680.

- crypto/x509: quadratic complexity when checking name constraints

    Due to the design of the name constraint checking algorithm, the processing time
    of some inputs scales non-linearly with respect to the size of the certificate.

    This affects programs which validate arbitrary certificate chains.

    Thanks to Jakub Ciolek for reporting this issue.

    This is CVE-2025-58187 and Go issue https://go.dev/issue/75681.

- crypto/tls: ALPN negotiation errors can contain arbitrary text

    The crypto/tls conn.Handshake method returns an error on the server-side when
    ALPN negotation fails which can contain arbitrary attacker controlled
    information provided by the client-side of the connection which is not escaped.

    This affects programs which log these errors without any additional form of
    sanitization, and may allow injection of attacker controlled information into
    logs.

    Thanks to National Cyber Security Centre Finland for reporting this issue.

    This is CVE-2025-58189 and Go issue https://go.dev/issue/75652.

- encoding/pem: quadratic complexity when parsing some invalid inputs

    Due to the design of the PEM parsing function, the processing time for some
    inputs scales non-linearly with respect to the size of the input.

    This affects programs which parse untrusted PEM inputs.

    Thanks to Jakub Ciolek for reporting this issue.

    This is CVE-2025-61723 and Go issue https://go.dev/issue/75676.

- net/url: insufficient validation of bracketed IPv6 hostnames

    The Parse function permitted values other than IPv6 addresses to be included in square brackets within the host component of a URL. RFC 3986 permits IPv6 addresses to be included within the host component, enclosed within square brackets. For example: "http://[::1]/". IPv4 addresses and hostnames must not appear within square brackets. Parse did not enforce this requirement.

    Thanks to Enze Wang, Jingcheng Yang and Zehui Miao of Tsinghua University for reporting this issue.

    This is CVE-2025-47912 and Go issue https://go.dev/issue/75678.

- encoding/asn1: pre-allocating memory when parsing DER payload can cause memory exhaustion

    When parsing DER payloads, memories were being allocated prior to fully validating the payloads.
    This permits an attacker to craft a big empty DER payload to cause memory exhaustion in functions such as asn1.Unmarshal, x509.ParseCertificateRequest, and ocsp.ParseResponse.

    Thanks to Jakub Ciolek for reporting this issue.

    This is CVE-2025-58185 and Go issue https://go.dev/issue/75671.

- net/http: lack of limit when parsing cookies can cause memory exhaustion

    Despite HTTP headers having a default limit of 1 MB, the number of cookies that can be parsed did not have a limit.
    By sending a lot of very small cookies such as "a=;", an attacker can make an HTTP server allocate a large amount of structs, causing large memory consumption.

    net/http now limits the number of cookies accepted to 3000, which can be adjusted using the httpcookiemaxnum GODEBUG option.

    Thanks to jub0bs for reporting this issue.

    This is CVE-2025-58186 and Go issue https://go.dev/issue/75672.

- crypto/x509: panic when validating certificates with DSA public keys

    Validating certificate chains which contain DSA public keys can cause programs
    to panic, due to a interface cast that assumes they implement the Equal method.

    This affects programs which validate arbitrary certificate chains.

    Thanks to Jakub Ciolek for reporting this issue.

    This is CVE-2025-58188 and Go issue https://go.dev/issue/75675.

- archive/tar: unbounded allocation when parsing GNU sparse map

    tar.Reader did not set a maximum size on the number of sparse region data blocks in GNU tar pax 1.0 sparse files. A maliciously-crafted archive containing a large number of sparse regions could cause a Reader to read an unbounded amount of data from the archive into memory. When reading from a compressed source, a small compressed input could result in large allocations.

    Thanks to Harshit Gupta (Mr HAX) - https://www.linkedin.com/in/iam-harshit-gupta/ for reporting this issue.

    This is CVE-2025-58183 and Go issue https://go.dev/issue/75677.

- net/textproto: excessive CPU consumption in Reader.ReadResponse

    The Reader.ReadResponse function constructed a response string through
    repeated string concatenation of lines. When the number of lines in a response is large,
    this could cause excessive CPU consumption.

    Thanks to Jakub Ciolek for reporting this issue.

    This is CVE-2025-61724 and Go issue https://go.dev/issue/75716.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit e598ea0176)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-10-07 21:51:36 +02:00
887030fbe8 Merge pull request #6522 from thaJeztah/28.x_bump_moby
Some checks failed
build / prepare (push) Has been cancelled
build / build (push) Has been cancelled
build / bin-image (push) Has been cancelled
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / tests (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 25, local) (push) Has been cancelled
e2e / tests (alpine, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 27, local) (push) Has been cancelled
e2e / tests (alpine, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (alpine, 28, local) (push) Has been cancelled
e2e / tests (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 25, local) (push) Has been cancelled
e2e / tests (debian, 27, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 27, local) (push) Has been cancelled
e2e / tests (debian, 28, connhelper-ssh) (push) Has been cancelled
e2e / tests (debian, 28, local) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-14) (push) Has been cancelled
test / host (macos-15) (push) Has been cancelled
test / host (macos-15-intel) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[28.x] vendor: github.com/docker/docker cd048300a487 (v28.5.0-dev)
2025-10-02 14:36:11 +00:00
9c6a0e0ba9 Merge pull request #6531 from thaJeztah/28.x_backport_bump_macos
[28.x backport] gha: add macOS 15, remove macOS 13 (deprecated)
2025-10-02 14:35:37 +00:00
f784471104 vendor: github.com/docker/docker cd048300a487 (v28.5.0-dev)
full diff: https://github.com/moby/moby/compare/v28.5.0-rc.1...cd048300a48700294339c9c91d2dcc691cb8f63b

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-01 17:34:28 +02:00
d7afcf9b98 Merge pull request #6529 from thaJeztah/28.x_backport_deprecate_ResolveDefaultContext
[28.x backport] cli/command: deprecate ResolveDefaultContext
2025-10-01 16:33:50 +02:00
9d9adf6346 gha: add macOS 15, remove macOS 13 (deprecated)
The macOS 13 runners are deprecated and will be removed on December 4th,
with brownouts in November;
https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 91d8c0bf62)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-01 12:05:21 +02:00
d4b7734f18 cli/command: deprecate ResolveDefaultContext
The ResolveDefaultContext function was exported in [cli@f820766] to allow
(unit) testing, but did not document that it was only exported for this
purpose. The only external use of this function is in buildx, which uses
it in a unit test that can be implemented without this function.

This patch deprecates the function so that we can remove it.

[cli@f820766]: f820766f6a

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 311a97a210)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-01 11:49:22 +02:00
a1061611fd Merge pull request #6519 from thaJeztah/28.x_backport_authconfig_no_direct_cast
[28.x backport] cli/command: explicitly map AuthConfig fields instead of a direct cast
2025-09-29 15:55:27 -07:00
5e42f826b4 Merge pull request #6518 from thaJeztah/28.x_backport_memstore_notfounderr
[28.x backport] cli/config/memorystore: remove unused IsErrValueNotFound
2025-09-29 15:13:54 -07:00
645c23bd13 Merge pull request #6514 from thaJeztah/28.x_backport_manifeststore_notfound
[28.x backport] cli/manifest/store: deprecate IsNotFound
2025-09-29 15:11:41 -07:00
e491078fc6 cli/command: explicitly map AuthConfig fields instead of a direct cast
Commit [cli@27b2797] forked the AuthConfig type from the API, and changed
existing code to do a direct cast / convert of the forked type to the API
type. This can cause issues if the API types diverges, such as the removal
of the Email field.

This patch explicitly maps each field to the corresponding API type, but
adds some TODOs, because various code-paths only included a subset of the
fields, which may be intentional for fields that were meant to be handled
on the daemon / registry-client only.

We should evaluate these conversions to make sure these fields should
be sent from the client or not (and possibly even removed from the API
type).

[cli@27b2797]: 27b2797f7d

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9f02d9643d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-29 13:15:05 +02:00
a3ffb8a148 cli/config/memorystore: remove unused IsErrValueNotFound
This utility was added in 9b83d5bbf9, but
was never used. Remove the utility, and rewrite the error returned to
implement the errdefs.NotFound interface, so that it can be detected
using the errdefs.IsNotFound() utility if needed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 3c78ac2aad)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-29 13:08:43 +02:00
a4ae5f2f7a cli/manifest/store: deprecate IsNotFound
Deprecate the IsNotFound utility in favor of errdefs.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f3fb7728c7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-26 23:35:20 +02:00
394991e2ab Merge pull request #6510 from thaJeztah/28.x_backport_auth
[28.x backport] cli/command/image: pushTrustedReference: internalize constructing indexInfo
2025-09-26 08:14:49 -07:00
e5bce5cd2d Merge pull request #6509 from thaJeztah/28.x_backport_dct_retiring
[28.x backport] trust: print deprecation warning when using hub Notary server
2025-09-26 08:13:53 -07:00
d5c181abf4 cli/command/image: pushTrustedReference: internalize constructing indexInfo
All information needed can be deducted from the image reference, which
is used to create a indexInfo, repoInfo, and to resolve auth-config.

In some situations this may result in resolving the auth-config twice
after it already was resolved to an encoded auth-config.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9a6313ed3b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-26 11:29:44 +02:00
0351ece9e5 trust: print deprecation warning when using hub Notary server
Docker Hub's Notary service is being retired, and now produces
failures in most cases. Add a warning when attempting to use
it, pending full removal of trust;
https://www.docker.com/blog/retiring-docker-content-trust/

With this PR:

    DOCKER_CONTENT_TRUST=1 docker pull -q hello-world
    WARNING: Docker is retiring DCT for Docker Official Images (DOI).
             For details, refer to https://docs.docker.com/go/dct-deprecation/

    could not validate the path to a trusted root: unable to retrieve valid leaf certificates

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 43b03ef2c5)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-26 11:24:04 +02:00
ec00b85794 cli/command/image: runPush: minor cleanups and linting issues
- Remove redundant intermediate variables
- Explicitly use an early return on error instead of combining with
  other checks.
- Fix unhandled errors and combine defers
- Remove outstanding TODO that unlikely will be addressed

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c36e67d7b6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-26 11:21:59 +02:00
a69c591c5a Merge pull request #6501 from thaJeztah/28.x_bump_docker_28.5
[28.x] vendor: github.com/docker/docker v28.5.0-rc.1
2025-09-25 17:33:08 +02:00
f9d2820a20 vendor: github.com/docker/docker v28.5.0-rc.1
full diff: https://github.com/docker/docker/compare/d21856f25dbe...v28.5.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-25 15:50:30 +02:00
48 changed files with 422 additions and 245 deletions

View File

@ -88,7 +88,7 @@ jobs:
fi
-
name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ env.ARTIFACT_NAME }}
path: /tmp/out/*

View File

@ -63,17 +63,17 @@ jobs:
name: Update Go
uses: actions/setup-go@v6
with:
go-version: "1.24.7"
go-version: "1.24.9"
-
name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: go
-
name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:go"

View File

@ -53,8 +53,9 @@ jobs:
fail-fast: false
matrix:
os:
- macos-13 # macOS 13 on Intel
- macos-14 # macOS 14 on arm64 (Apple Silicon M1)
- macos-14 # macOS 14 on arm64 (Apple Silicon M1)
- macos-15-intel # macOS 15 on Intel
- macos-15 # macOS 15 on arm64 (Apple Silicon M1)
# - windows-2022 # FIXME: some tests are failing on the Windows runner, as well as on Appveyor since June 24, 2018: https://ci.appveyor.com/project/docker/cli/history
steps:
-
@ -66,7 +67,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v6
with:
go-version: "1.24.7"
go-version: "1.24.9"
-
name: Test
run: |

View File

@ -5,7 +5,7 @@ run:
# which causes it to fallback to go1.17 semantics.
#
# TODO(thaJeztah): update "usetesting" settings to enable go1.24 features once our minimum version is go1.24
go: "1.24.7"
go: "1.24.9"
timeout: 5m

View File

@ -8,13 +8,13 @@ ARG BASE_VARIANT=alpine
ARG ALPINE_VERSION=3.21
ARG BASE_DEBIAN_DISTRO=bookworm
ARG GO_VERSION=1.24.7
ARG GO_VERSION=1.24.9
ARG XX_VERSION=1.6.1
ARG GOVERSIONINFO_VERSION=v1.4.1
# GOTESTSUM_VERSION sets the version of gotestsum to install in the dev container.
# It must be a valid tag in the https://github.com/gotestyourself/gotestsum repository.
ARG GOTESTSUM_VERSION=v1.12.3
ARG GOTESTSUM_VERSION=v1.13.0
# BUILDX_VERSION sets the version of buildx to use for the e2e tests.
# It must be a tag in the docker.io/docker/buildx-bin image repository

View File

@ -38,6 +38,7 @@ func AddPluginCommandStubs(dockerCLI config.Provider, rootCmd *cobra.Command) (e
rootCmd.AddCommand(&cobra.Command{
Use: p.Name,
Short: p.ShortDescription,
Hidden: p.Hidden,
Run: func(_ *cobra.Command, _ []string) {},
Annotations: annotations,
DisableFlagParsing: true,

View File

@ -33,4 +33,6 @@ type Metadata struct {
ShortDescription string `json:",omitempty"`
// URL is a pointer to the plugin's homepage.
URL string `json:",omitempty"`
// Hidden hides the plugin in completion and help message output.
Hidden bool `json:",omitempty"`
}

View File

@ -376,13 +376,10 @@ func orchestratorSubCommands(cmd *cobra.Command) []*cobra.Command {
func allManagementSubCommands(cmd *cobra.Command) []*cobra.Command {
cmds := []*cobra.Command{}
for _, sub := range cmd.Commands() {
if isPlugin(sub) {
if invalidPluginReason(sub) == "" {
cmds = append(cmds, sub)
}
if invalidPluginReason(sub) != "" {
continue
}
if sub.IsAvailableCommand() && sub.HasSubCommands() {
if sub.IsAvailableCommand() && (isPlugin(sub) || sub.HasSubCommands()) {
cmds = append(cmds, sub)
}
}

View File

@ -56,6 +56,33 @@ func TestInvalidPlugin(t *testing.T) {
assert.DeepEqual(t, invalidPlugins(root), []*cobra.Command{sub1}, cmpopts.IgnoreUnexported(cobra.Command{}))
}
func TestHiddenPlugin(t *testing.T) {
root := &cobra.Command{Use: "root"}
sub1 := &cobra.Command{
Use: "sub1",
Hidden: true,
Annotations: map[string]string{
metadata.CommandAnnotationPlugin: "true",
},
Run: func(cmd *cobra.Command, args []string) {},
}
sub1sub1 := &cobra.Command{Use: "sub1sub1"}
sub1sub2 := &cobra.Command{Use: "sub1sub2"}
sub2 := &cobra.Command{
Use: "sub2",
Annotations: map[string]string{
metadata.CommandAnnotationPlugin: "true",
},
Run: func(cmd *cobra.Command, args []string) {},
}
root.AddCommand(sub1, sub2)
sub1.AddCommand(sub1sub1, sub1sub2)
assert.DeepEqual(t, allManagementSubCommands(root), []*cobra.Command{sub2}, cmpopts.IgnoreFields(cobra.Command{}, "Run"), cmpopts.IgnoreUnexported(cobra.Command{}))
}
func TestCommandAliases(t *testing.T) {
root := &cobra.Command{Use: "root"}
sub := &cobra.Command{Use: "subcommand", Aliases: []string{"alias1", "alias2"}}

View File

@ -272,7 +272,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
cli.contextStore = &ContextStoreWithDefault{
Store: store.New(config.ContextStoreDir(), *cli.contextStoreConfig),
Resolver: func() (*DefaultContext, error) {
return ResolveDefaultContext(cli.options, *cli.contextStoreConfig)
return resolveDefaultContext(cli.options, *cli.contextStoreConfig)
},
}
@ -309,7 +309,7 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
contextStore := &ContextStoreWithDefault{
Store: store.New(config.ContextStoreDir(), storeConfig),
Resolver: func() (*DefaultContext, error) {
return ResolveDefaultContext(opts, storeConfig)
return resolveDefaultContext(opts, storeConfig)
},
}
endpoint, err := resolveDockerEndpoint(contextStore, resolveContextName(opts, configFile))

View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"net"
"os"
"path"
"path/filepath"
@ -350,7 +351,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
// Validate the input mac address
if copts.macAddress != "" {
if _, err := opts.ValidateMACAddress(copts.macAddress); err != nil {
if _, err := net.ParseMAC(strings.TrimSpace(copts.macAddress)); err != nil {
return nil, errors.Errorf("%s is not a valid mac address", copts.macAddress)
}
}
@ -883,7 +884,7 @@ func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*networktypes.End
}
}
if ep.MacAddress != "" {
if _, err := opts.ValidateMACAddress(ep.MacAddress); err != nil {
if _, err := net.ParseMAC(strings.TrimSpace(ep.MacAddress)); err != nil {
return nil, errors.Errorf("%s is not a valid mac address", ep.MacAddress)
}
epConfig.MacAddress = ep.MacAddress

View File

@ -52,7 +52,14 @@ type EndpointDefaultResolver interface {
}
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
//
// Deprecated: this function is exported for testing and meant for internal use. It will be removed in the next release.
func ResolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
return resolveDefaultContext(opts, config)
}
// resolveDefaultContext creates a Metadata for the current CLI invocation parameters
func resolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
contextTLSData := store.ContextTLSData{
Endpoints: make(map[string]store.EndpointTLSData),
}

View File

@ -59,7 +59,7 @@ func TestDefaultContextInitializer(t *testing.T) {
assert.NilError(t, err)
t.Setenv("DOCKER_HOST", "ssh://someswarmserver")
cli.configFile = &configfile.ConfigFile{}
ctx, err := ResolveDefaultContext(&cliflags.ClientOptions{
ctx, err := resolveDefaultContext(&cliflags.ClientOptions{
TLS: true,
TLSOptions: &tlsconfig.Options{
CAFile: "./testdata/ca.pem",

View File

@ -12,7 +12,7 @@
// based on https://github.com/golang/go/blob/master/src/text/tabwriter/tabwriter.go Last modified 690ac40 on 31 Jan
//nolint:gocyclo,nakedret,unused // ignore linting errors, so that we can stick close to upstream
//nolint:gocyclo,gofumpt,nakedret,unused // ignore linting errors, so that we can stick close to upstream
package tabwriter
import (

View File

@ -184,7 +184,6 @@ func (out *lastProgressOutput) WriteProgress(prog progress.Progress) error {
//nolint:gocyclo
func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions) error {
var (
err error
buildCtx io.ReadCloser
dockerfileCtx io.ReadCloser
contextDir string
@ -266,7 +265,7 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
}
if err := build.ValidateContextDirectory(contextDir, excludes); err != nil {
return errors.Wrap(err, "error checking context")
return errors.Wrap(err, "checking context")
}
// And canonicalize dockerfile name to a platform-independent one
@ -340,11 +339,19 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
configFile := dockerCli.ConfigFile()
creds, _ := configFile.GetAllCredentials()
authConfigs := make(map[string]registrytypes.AuthConfig, len(creds))
for k, auth := range creds {
authConfigs[k] = registrytypes.AuthConfig(auth)
for k, authConfig := range creds {
authConfigs[k] = registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
}
}
buildOpts := imageBuildOptions(dockerCli, options)
buildOpts.Version = buildtypes.BuilderV1
buildOpts.Dockerfile = relDockerfile
buildOpts.AuthConfigs = authConfigs
buildOpts.RemoteContext = remote
@ -354,7 +361,6 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
if options.quiet {
_, _ = fmt.Fprintf(dockerCli.Err(), "%s", progBuff)
}
cancel()
return err
}
defer response.Body.Close()
@ -371,7 +377,8 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
err = jsonstream.Display(ctx, response.Body, streams.NewOut(buildBuff), jsonstream.WithAuxCallback(aux))
if err != nil {
if jerr, ok := err.(*jsonstream.JSONError); ok {
var jerr *jsonstream.JSONError
if errors.As(err, &jerr) {
// If no error code is set, default to 1
if jerr.Code == 0 {
jerr.Code = 1
@ -535,6 +542,7 @@ func replaceDockerfileForContentTrust(ctx context.Context, inputTarStream io.Rea
func imageBuildOptions(dockerCli command.Cli, options buildOptions) buildtypes.ImageBuildOptions {
configFile := dockerCli.ConfigFile()
return buildtypes.ImageBuildOptions{
Version: buildtypes.BuilderV1,
Memory: options.memory.Value(),
MemorySwap: options.memorySwap.Value(),
Tags: options.tags.GetSlice(),

View File

@ -25,9 +25,14 @@ import (
"github.com/pkg/errors"
)
// DefaultDockerfileName is the Default filename with Docker commands, read by docker build
//
// Deprecated: this const is no longer used and will be removed in the next release.
const DefaultDockerfileName string = "Dockerfile"
const (
// DefaultDockerfileName is the Default filename with Docker commands, read by docker build
DefaultDockerfileName string = "Dockerfile"
// defaultDockerfileName is the Default filename with Docker commands, read by docker build
defaultDockerfileName string = "Dockerfile"
// archiveHeaderSize is the number of bytes in an archive header
archiveHeaderSize = 512
)
@ -80,7 +85,7 @@ func ValidateContextDirectory(srcPath string, excludes []string) error {
if err != nil && os.IsPermission(err) {
return errors.Errorf("no permission to read from '%s'", filePath)
}
currentFile.Close()
_ = currentFile.Close()
}
return nil
})
@ -97,10 +102,21 @@ func filepathMatches(matcher *patternmatcher.PatternMatcher, file string) (bool,
// DetectArchiveReader detects whether the input stream is an archive or a
// Dockerfile and returns a buffered version of input, safe to consume in lieu
// of input. If an archive is detected, isArchive is set to true, and to false
// of input. If an archive is detected, ok is set to true, and to false
// otherwise, in which case it is safe to assume input represents the contents
// of a Dockerfile.
func DetectArchiveReader(input io.ReadCloser) (rc io.ReadCloser, isArchive bool, err error) {
//
// Deprecated: this utility was only used internally, and will be removed in the next release.
func DetectArchiveReader(input io.ReadCloser) (rc io.ReadCloser, ok bool, err error) {
return detectArchiveReader(input)
}
// detectArchiveReader detects whether the input stream is an archive or a
// Dockerfile and returns a buffered version of input, safe to consume in lieu
// of input. If an archive is detected, ok is set to true, and to false
// otherwise, in which case it is safe to assume input represents the contents
// of a Dockerfile.
func detectArchiveReader(input io.ReadCloser) (rc io.ReadCloser, ok bool, err error) {
buf := bufio.NewReader(input)
magic, err := buf.Peek(archiveHeaderSize * 2)
@ -108,13 +124,22 @@ func DetectArchiveReader(input io.ReadCloser) (rc io.ReadCloser, isArchive bool,
return nil, false, errors.Errorf("failed to peek context header from STDIN: %v", err)
}
return newReadCloserWrapper(buf, func() error { return input.Close() }), IsArchive(magic), nil
return newReadCloserWrapper(buf, func() error { return input.Close() }), isArchive(magic), nil
}
// WriteTempDockerfile writes a Dockerfile stream to a temporary file with a
// name specified by DefaultDockerfileName and returns the path to the
// name specified by defaultDockerfileName and returns the path to the
// temporary directory containing the Dockerfile.
//
// Deprecated: this utility was only used internally, and will be removed in the next release.
func WriteTempDockerfile(rc io.ReadCloser) (dockerfileDir string, err error) {
return writeTempDockerfile(rc)
}
// writeTempDockerfile writes a Dockerfile stream to a temporary file with a
// name specified by defaultDockerfileName and returns the path to the
// temporary directory containing the Dockerfile.
func writeTempDockerfile(rc io.ReadCloser) (dockerfileDir string, err error) {
// err is a named return value, due to the defer call below.
dockerfileDir, err = os.MkdirTemp("", "docker-build-tempdockerfile-")
if err != nil {
@ -126,7 +151,7 @@ func WriteTempDockerfile(rc io.ReadCloser) (dockerfileDir string, err error) {
}
}()
f, err := os.Create(filepath.Join(dockerfileDir, DefaultDockerfileName))
f, err := os.Create(filepath.Join(dockerfileDir, defaultDockerfileName))
if err != nil {
return "", err
}
@ -141,12 +166,12 @@ func WriteTempDockerfile(rc io.ReadCloser) (dockerfileDir string, err error) {
// Dockerfile or tar archive. Returns a tar archive used as a context and a
// path to the Dockerfile inside the tar.
func GetContextFromReader(rc io.ReadCloser, dockerfileName string) (out io.ReadCloser, relDockerfile string, err error) {
rc, isArchive, err := DetectArchiveReader(rc)
rc, ok, err := detectArchiveReader(rc)
if err != nil {
return nil, "", err
}
if isArchive {
if ok {
return rc, dockerfileName, nil
}
@ -159,7 +184,7 @@ func GetContextFromReader(rc io.ReadCloser, dockerfileName string) (out io.ReadC
return nil, "", errors.New("ambiguous Dockerfile source: both stdin and flag correspond to Dockerfiles")
}
dockerfileDir, err := WriteTempDockerfile(rc)
dockerfileDir, err := writeTempDockerfile(rc)
if err != nil {
return nil, "", err
}
@ -171,14 +196,22 @@ func GetContextFromReader(rc io.ReadCloser, dockerfileName string) (out io.ReadC
return newReadCloserWrapper(tarArchive, func() error {
err := tarArchive.Close()
os.RemoveAll(dockerfileDir)
_ = os.RemoveAll(dockerfileDir)
return err
}), DefaultDockerfileName, nil
}), defaultDockerfileName, nil
}
// IsArchive checks for the magic bytes of a tar or any supported compression
// algorithm.
//
// Deprecated: this utility was used internally and will be removed in the next release.
func IsArchive(header []byte) bool {
return isArchive(header)
}
// isArchive checks for the magic bytes of a tar or any supported compression
// algorithm.
func isArchive(header []byte) bool {
if compression.Detect(header) != compression.None {
return true
}
@ -201,7 +234,7 @@ func GetContextFromGitURL(gitURL, dockerfileName string) (string, string, error)
return "", "", errors.Wrapf(err, "unable to 'git clone' to temporary context directory")
}
absContextDir, err = ResolveAndValidateContextPath(absContextDir)
absContextDir, err = resolveAndValidateContextPath(absContextDir)
if err != nil {
return "", "", err
}
@ -242,7 +275,7 @@ func getWithStatusError(url string) (resp *http.Response, err error) {
}
msg := fmt.Sprintf("failed to GET %s with status %s", url, resp.Status)
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
_ = resp.Body.Close()
if err != nil {
return nil, errors.Wrapf(err, "%s: error reading body", msg)
}
@ -254,7 +287,7 @@ func getWithStatusError(url string) (resp *http.Response, err error) {
// the relative path of the dockerfile in that context directory, and a non-nil
// error on success.
func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, error) {
localDir, err := ResolveAndValidateContextPath(localDir)
localDir, err := resolveAndValidateContextPath(localDir)
if err != nil {
return "", "", err
}
@ -274,7 +307,18 @@ func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, er
// ResolveAndValidateContextPath uses the given context directory for a `docker build`
// and returns the absolute path to the context directory.
//
// Deprecated: this utility was used internally and will be removed in the next
// release. Use [DetectContextType] to detect the context-type, and use
// [GetContextFromLocalDir], [GetContextFromLocalDir], [GetContextFromGitURL],
// or [GetContextFromURL] instead.
func ResolveAndValidateContextPath(givenContextDir string) (string, error) {
return resolveAndValidateContextPath(givenContextDir)
}
// resolveAndValidateContextPath uses the given context directory for a `docker build`
// and returns the absolute path to the context directory.
func resolveAndValidateContextPath(givenContextDir string) (string, error) {
absContextDir, err := filepath.Abs(givenContextDir)
if err != nil {
return "", errors.Errorf("unable to get absolute context directory of given context directory %q: %v", givenContextDir, err)
@ -318,12 +362,12 @@ func getDockerfileRelPath(absContextDir, givenDockerfile string) (string, error)
if absDockerfile == "" {
// No -f/--file was specified so use the default relative to the
// context directory.
absDockerfile = filepath.Join(absContextDir, DefaultDockerfileName)
absDockerfile = filepath.Join(absContextDir, defaultDockerfileName)
// Just to be nice ;-) look for 'dockerfile' too but only
// use it if we found it, otherwise ignore this check
if _, err = os.Lstat(absDockerfile); os.IsNotExist(err) {
altPath := filepath.Join(absContextDir, strings.ToLower(DefaultDockerfileName))
altPath := filepath.Join(absContextDir, strings.ToLower(defaultDockerfileName))
if _, err = os.Lstat(altPath); err == nil {
absDockerfile = altPath
}
@ -374,7 +418,7 @@ func isUNC(path string) bool {
// the relative path to the dockerfile in the context.
func AddDockerfileToBuildContext(dockerfileCtx io.ReadCloser, buildCtx io.ReadCloser) (io.ReadCloser, string, error) {
file, err := io.ReadAll(dockerfileCtx)
dockerfileCtx.Close()
_ = dockerfileCtx.Close()
if err != nil {
return nil, "", err
}
@ -438,17 +482,19 @@ func Compress(buildCtx io.ReadCloser) (io.ReadCloser, error) {
go func() {
compressWriter, err := compression.CompressStream(pipeWriter, archive.Gzip)
if err != nil {
pipeWriter.CloseWithError(err)
_ = pipeWriter.CloseWithError(err)
}
defer buildCtx.Close()
defer func() {
_ = buildCtx.Close()
}()
if _, err := io.Copy(compressWriter, buildCtx); err != nil {
pipeWriter.CloseWithError(errors.Wrap(err, "failed to compress context"))
compressWriter.Close()
_ = pipeWriter.CloseWithError(errors.Wrap(err, "failed to compress context"))
_ = compressWriter.Close()
return
}
compressWriter.Close()
pipeWriter.Close()
_ = compressWriter.Close()
_ = pipeWriter.Close()
}()
return pipeReader, nil

View File

@ -31,7 +31,7 @@ func prepareNoFiles(t *testing.T) string {
func prepareOneFile(t *testing.T) string {
t.Helper()
contextDir := createTestTempDir(t)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
return contextDir
}
@ -66,7 +66,7 @@ func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) {
func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
contextDir := createTestTempDir(t)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
chdir(t, contextDir)
@ -74,23 +74,23 @@ func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
assert.NilError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Check(t, is.Equal(defaultDockerfileName, relDockerfile))
}
func TestGetContextFromLocalDirWithDockerfile(t *testing.T) {
contextDir := createTestTempDir(t)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "")
assert.NilError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Check(t, is.Equal(defaultDockerfileName, relDockerfile))
}
func TestGetContextFromLocalDirLocalFile(t *testing.T) {
contextDir := createTestTempDir(t)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
testFilename := createTestTempFile(t, contextDir, "tmpTest", "test")
absContextDir, relDockerfile, err := GetContextFromLocalDir(testFilename, "")
@ -112,13 +112,13 @@ func TestGetContextFromLocalDirWithCustomDockerfile(t *testing.T) {
contextDir := createTestTempDir(t)
chdir(t, contextDir)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, DefaultDockerfileName)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, defaultDockerfileName)
assert.NilError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Check(t, is.Equal(defaultDockerfileName, relDockerfile))
}
func TestGetContextFromReaderString(t *testing.T) {
@ -135,7 +135,7 @@ func TestGetContextFromReaderString(t *testing.T) {
}
buff := new(bytes.Buffer)
buff.ReadFrom(tarReader)
_, _ = buff.ReadFrom(tarReader)
contents := buff.String()
_, err = tarReader.Next()
@ -150,8 +150,8 @@ func TestGetContextFromReaderString(t *testing.T) {
t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents)
}
if relDockerfile != DefaultDockerfileName {
t.Fatalf("Relative path not equals %s, got: %s", DefaultDockerfileName, relDockerfile)
if relDockerfile != defaultDockerfileName {
t.Fatalf("Relative path not equals %s, got: %s", defaultDockerfileName, relDockerfile)
}
}
@ -164,12 +164,12 @@ func TestGetContextFromReaderStringConflict(t *testing.T) {
func TestGetContextFromReaderTar(t *testing.T) {
contextDir := createTestTempDir(t)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
createTestTempFile(t, contextDir, defaultDockerfileName, dockerfileContents)
tarStream, err := archive.Tar(contextDir, compression.None)
assert.NilError(t, err)
tarArchive, relDockerfile, err := GetContextFromReader(tarStream, DefaultDockerfileName)
tarArchive, relDockerfile, err := GetContextFromReader(tarStream, defaultDockerfileName)
assert.NilError(t, err)
tarReader := tar.NewReader(tarArchive)
@ -177,12 +177,12 @@ func TestGetContextFromReaderTar(t *testing.T) {
header, err := tarReader.Next()
assert.NilError(t, err)
if header.Name != DefaultDockerfileName {
t.Fatalf("Dockerfile name should be: %s, got: %s", DefaultDockerfileName, header.Name)
if header.Name != defaultDockerfileName {
t.Fatalf("Dockerfile name should be: %s, got: %s", defaultDockerfileName, header.Name)
}
buff := new(bytes.Buffer)
buff.ReadFrom(tarReader)
_, _ = buff.ReadFrom(tarReader)
contents := buff.String()
_, err = tarReader.Next()
@ -197,8 +197,8 @@ func TestGetContextFromReaderTar(t *testing.T) {
t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents)
}
if relDockerfile != DefaultDockerfileName {
t.Fatalf("Relative path not equals %s, got: %s", DefaultDockerfileName, relDockerfile)
if relDockerfile != defaultDockerfileName {
t.Fatalf("Relative path not equals %s, got: %s", defaultDockerfileName, relDockerfile)
}
}
@ -223,7 +223,7 @@ func TestValidateContextDirectoryWithOneFile(t *testing.T) {
}
func TestValidateContextDirectoryWithOneFileExcludes(t *testing.T) {
testValidateContextDirectory(t, prepareOneFile, []string{DefaultDockerfileName})
testValidateContextDirectory(t, prepareOneFile, []string{defaultDockerfileName})
}
// createTestTempDir creates a temporary directory for testing. It returns the
@ -263,7 +263,7 @@ func chdir(t *testing.T, dir string) {
}
func TestIsArchive(t *testing.T) {
testcases := []struct {
tests := []struct {
doc string
header []byte
expected bool
@ -289,13 +289,15 @@ func TestIsArchive(t *testing.T) {
expected: false,
},
}
for _, testcase := range testcases {
assert.Check(t, is.Equal(testcase.expected, IsArchive(testcase.header)), testcase.doc)
for _, tc := range tests {
t.Run(tc.doc, func(t *testing.T) {
assert.Check(t, is.Equal(tc.expected, isArchive(tc.header)), tc.doc)
})
}
}
func TestDetectArchiveReader(t *testing.T) {
testcases := []struct {
tests := []struct {
file string
desc string
expected bool
@ -316,14 +318,18 @@ func TestDetectArchiveReader(t *testing.T) {
expected: false,
},
}
for _, testcase := range testcases {
content, err := os.Open(testcase.file)
assert.NilError(t, err)
defer content.Close()
for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
content, err := os.Open(tc.file)
assert.NilError(t, err)
defer func() {
_ = content.Close()
}()
_, isArchive, err := DetectArchiveReader(content)
assert.NilError(t, err)
assert.Check(t, is.Equal(testcase.expected, isArchive), testcase.file)
_, isArchive, err := detectArchiveReader(content)
assert.NilError(t, err)
assert.Check(t, is.Equal(tc.expected, isArchive), tc.file)
})
}
}

View File

@ -21,7 +21,9 @@ func ReadDockerignore(contextDir string) ([]string, error) {
case err != nil:
return nil, err
}
defer f.Close()
defer func() {
_ = f.Close()
}()
patterns, err := ignorefile.ReadAll(f)
if err != nil {

View File

@ -17,11 +17,9 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/cli/internal/tui"
"github.com/docker/docker/api/types/auxprogress"
"github.com/docker/docker/api/types/image"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/morikuni/aec"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
@ -100,9 +98,11 @@ To push the complete multi-platform image, remove the --platform flag.
}
ref, err := reference.ParseNormalizedNamed(opts.remote)
switch {
case err != nil:
if err != nil {
return err
}
switch {
case opts.all && !reference.IsNameOnly(ref):
return errors.New("tag can't be used with --all-tags/-a")
case !opts.all && reference.IsNameOnly(ref):
@ -112,43 +112,37 @@ To push the complete multi-platform image, remove the --platform flag.
}
}
// Resolve the Repository name from fqn to RepositoryInfo
indexInfo := registry.NewIndexInfo(ref)
// Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(dockerCli.ConfigFile(), indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
encodedAuth, err := command.RetrieveAuthTokenFromImage(dockerCli.ConfigFile(), ref.String())
if err != nil {
return err
}
options := image.PushOptions{
responseBody, err := dockerCli.Client().ImagePush(ctx, reference.FamiliarString(ref), image.PushOptions{
All: opts.all,
RegistryAuth: encodedAuth,
PrivilegeFunc: nil,
Platform: platform,
}
responseBody, err := dockerCli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
})
if err != nil {
return err
}
defer func() {
_ = responseBody.Close()
for _, note := range notes {
out.PrintNote(note)
}
}()
defer responseBody.Close()
if !opts.untrusted {
// TODO pushTrustedReference currently doesn't respect `--quiet`
return pushTrustedReference(ctx, dockerCli, indexInfo, ref, authConfig, responseBody)
return pushTrustedReference(ctx, dockerCli, ref, responseBody)
}
if opts.quiet {
err = jsonstream.Display(ctx, responseBody, streams.NewOut(io.Discard), jsonstream.WithAuxCallback(handleAux()))
if err == nil {
fmt.Fprintln(dockerCli.Out(), ref.String())
_, _ = fmt.Fprintln(dockerCli.Out(), ref.String())
}
return err
}

View File

@ -12,6 +12,7 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/jsonstream"
"github.com/docker/cli/internal/registry"
"github.com/docker/docker/api/types/image"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/opencontainers/go-digest"
@ -42,12 +43,18 @@ func newNotaryClient(cli command.Streams, imgRefAndAuth trust.ImageRefAndAuth) (
}
// pushTrustedReference pushes a canonical reference to the trust server.
func pushTrustedReference(ctx context.Context, ioStreams command.Streams, indexInfo *registrytypes.IndexInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
func pushTrustedReference(ctx context.Context, dockerCLI command.Cli, ref reference.Named, responseBody io.Reader) error {
// Resolve the Repository name from fqn to RepositoryInfo, and create an
// IndexInfo. Docker Content Trust uses the IndexInfo.Official field to
// select the right domain for Docker Hub's Notary server;
// https://github.com/docker/cli/blob/v28.4.0/cli/trust/trust.go#L65-L79
indexInfo := registry.NewIndexInfo(ref)
repoInfo := &trust.RepositoryInfo{
Name: reference.TrimNamed(ref),
Index: indexInfo,
}
return trust.PushTrustedReference(ctx, ioStreams, repoInfo, ref, authConfig, in, command.UserAgent())
authConfig := command.ResolveAuthConfig(dockerCLI.ConfigFile(), indexInfo)
return trust.PushTrustedReference(ctx, dockerCLI, repoInfo, ref, authConfig, responseBody, command.UserAgent())
}
// trustedPull handles content trust pulling of an image

View File

@ -5,6 +5,7 @@ import (
"fmt"
"path/filepath"
"github.com/containerd/errdefs"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/config"
@ -97,7 +98,7 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error {
manifestStore := newManifestStore(dockerCLI)
imageManifest, err := manifestStore.Get(targetRef, imgRef)
switch {
case store.IsNotFound(err):
case errdefs.IsNotFound(err):
return fmt.Errorf("manifest for image %s does not exist in %s", opts.image, opts.target)
case err != nil:
return err

View File

@ -4,9 +4,9 @@ import (
"context"
"fmt"
"github.com/containerd/errdefs"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/manifest/store"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -44,7 +44,7 @@ func createManifestList(ctx context.Context, dockerCLI command.Cli, args []strin
manifestStore := newManifestStore(dockerCLI)
_, err = manifestStore.GetList(targetRef)
switch {
case store.IsNotFound(err):
case errdefs.IsNotFound(err):
// New manifest list
case err != nil:
return err

View File

@ -3,9 +3,9 @@ package manifest
import (
"context"
"github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/manifest/store"
"github.com/docker/cli/cli/manifest/types"
)
@ -72,7 +72,7 @@ func normalizeReference(ref string) (reference.Named, error) {
func getManifest(ctx context.Context, dockerCLI command.Cli, listRef, namedRef reference.Named, insecure bool) (types.ImageManifest, error) {
data, err := newManifestStore(dockerCLI).Get(listRef, namedRef)
switch {
case store.IsNotFound(err):
case errdefs.IsNotFound(err):
return newRegistryClient(dockerCLI, insecure).GetManifest(ctx, namedRef)
case err != nil:
return types.ImageManifest{}, err

View File

@ -77,7 +77,16 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
}
a, _ := cfg.GetAuthConfig(configKey)
return registrytypes.AuthConfig(a)
return registrytypes.AuthConfig{
Username: a.Username,
Password: a.Password,
ServerAddress: a.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: a.Auth,
IdentityToken: a.IdentityToken,
RegistryToken: a.RegistryToken,
}
}
// GetDefaultAuthConfig gets the default auth config given a serverAddress
@ -86,19 +95,27 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
if !isDefaultRegistry {
serverAddress = credentials.ConvertToHostname(serverAddress)
}
authconfig := configtypes.AuthConfig{}
authCfg := configtypes.AuthConfig{}
var err error
if checkCredStore {
authconfig, err = cfg.GetAuthConfig(serverAddress)
authCfg, err = cfg.GetAuthConfig(serverAddress)
if err != nil {
return registrytypes.AuthConfig{
ServerAddress: serverAddress,
}, err
}
}
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
return registrytypes.AuthConfig(authconfig), nil
return registrytypes.AuthConfig{
Username: authCfg.Username,
Password: authCfg.Password,
ServerAddress: serverAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authCfg.Auth,
IdentityToken: "",
RegistryToken: authCfg.RegistryToken,
}, nil
}
// PromptUserForCredentials handles the CLI prompt for the user to input
@ -213,7 +230,16 @@ func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (strin
return "", err
}
encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig(authConfig))
encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
})
if err != nil {
return "", err
}

View File

@ -259,12 +259,30 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st
return "", err
}
response, err := loginWithRegistry(ctx, dockerCLI.Client(), registrytypes.AuthConfig(*authConfig))
response, err := loginWithRegistry(ctx, dockerCLI.Client(), registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
})
if err != nil {
return "", err
}
if err = storeCredentials(dockerCLI.ConfigFile(), registrytypes.AuthConfig(*authConfig)); err != nil {
if err = storeCredentials(dockerCLI.ConfigFile(), registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
}); err != nil {
return "", err
}
@ -273,7 +291,16 @@ func loginWithDeviceCodeFlow(ctx context.Context, dockerCLI command.Cli) (msg st
func storeCredentials(cfg *configfile.ConfigFile, authConfig registrytypes.AuthConfig) error {
creds := cfg.GetCredentialsStore(authConfig.ServerAddress)
if err := creds.Store(configtypes.AuthConfig(authConfig)); err != nil {
if err := creds.Store(configtypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
}); err != nil {
return errors.Errorf("Error saving credentials: %v", err)
}

View File

@ -102,7 +102,16 @@ func getAuth(dockerCLI command.Cli, reposName string) (encodedAuth string, err e
// "no credentials found"). We'll get an error when search failed,
// so fine to ignore in most situations.
authConfig, _ := dockerCLI.ConfigFile().GetAuthConfig(authCfgKey)
return registrytypes.EncodeAuthConfig(registrytypes.AuthConfig(authConfig))
return registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
})
}
// splitReposSearchTerm breaks a search term into an index name and remote name

View File

@ -58,8 +58,17 @@ func TestGetDefaultAuthConfig(t *testing.T) {
},
}
cfg := configfile.New("filename")
for _, authconfig := range testAuthConfigs {
assert.Check(t, cfg.GetCredentialsStore(authconfig.ServerAddress).Store(configtypes.AuthConfig(authconfig)))
for _, authConfig := range testAuthConfigs {
assert.Check(t, cfg.GetCredentialsStore(authConfig.ServerAddress).Store(configtypes.AuthConfig{
Username: authConfig.Username,
Password: authConfig.Password,
ServerAddress: authConfig.ServerAddress,
// TODO(thaJeztah): Are these expected to be included?
Auth: authConfig.Auth,
IdentityToken: authConfig.IdentityToken,
RegistryToken: authConfig.RegistryToken,
}))
}
for _, tc := range testCases {
serverAddress := tc.inputServerAddress

View File

@ -4,6 +4,7 @@
package loader
import (
"fmt"
"reflect"
"sort"
@ -116,7 +117,11 @@ func toServicePortConfigsMap(s any) (map[any]any, error) {
}
m := map[any]any{}
for _, p := range ports {
m[p.Published] = p
protocol := "tcp"
if p.Protocol != "" {
protocol = p.Protocol
}
m[fmt.Sprintf("%d%s", p.Published, protocol)] = p
}
return m, nil
}

View File

@ -848,6 +848,8 @@ func TestLoadMultipleConfigs(t *testing.T) {
"ports": []any{
"8080:80",
"9090:90",
"53:53/tcp",
"53:53/udp",
},
"labels": []any{
"foo=bar",
@ -925,6 +927,18 @@ func TestLoadMultipleConfigs(t *testing.T) {
},
},
Ports: []types.ServicePortConfig{
{
Mode: "ingress",
Target: 53,
Published: 53,
Protocol: "tcp",
},
{
Mode: "ingress",
Target: 53,
Published: 53,
Protocol: "udp",
},
{
Target: 81,
Published: 8080,

View File

@ -3,7 +3,6 @@
package memorystore
import (
"errors"
"fmt"
"maps"
"os"
@ -13,12 +12,17 @@ import (
"github.com/docker/cli/cli/config/types"
)
var errValueNotFound = errors.New("value not found")
// notFoundErr is the error returned when a plugin could not be found.
type notFoundErr string
func IsErrValueNotFound(err error) bool {
return errors.Is(err, errValueNotFound)
func (notFoundErr) NotFound() {}
func (e notFoundErr) Error() string {
return string(e)
}
var errValueNotFound notFoundErr = "value not found"
type Config struct {
lock sync.RWMutex
memoryCredentials map[string]types.AuthConfig

View File

@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"
"github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/docker/cli/cli/manifest/types"
"github.com/docker/distribution/manifest/manifestlist"
@ -152,27 +153,13 @@ func makeFilesafeName(ref string) string {
return strings.ReplaceAll(fileName, "/", "_")
}
type notFoundError struct {
object string
func newNotFoundError(ref string) error {
return errdefs.ErrNotFound.WithMessage("No such manifest: " + ref)
}
func newNotFoundError(ref string) *notFoundError {
return &notFoundError{object: ref}
}
func (n *notFoundError) Error() string {
return "No such manifest: " + n.object
}
// NotFound interface
func (*notFoundError) NotFound() {}
// IsNotFound returns true if the error is a not found error
//
// Deprecated: use [errdefs.IsNotFound]. This function will be removed in the next release.
func IsNotFound(err error) bool {
_, ok := err.(notFound)
return ok
}
type notFound interface {
NotFound()
return errdefs.IsNotFound(err)
}

View File

@ -4,6 +4,7 @@ import (
"os"
"testing"
"github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/docker/cli/cli/manifest/types"
"github.com/google/go-cmp/cmp"
@ -86,7 +87,7 @@ func TestStoreSaveAndGet(t *testing.T) {
actual, err := store.Get(tc.listRef, tc.manifestRef)
if tc.expectedErr != "" {
assert.Error(t, err, tc.expectedErr)
assert.Check(t, IsNotFound(err))
assert.Check(t, errdefs.IsNotFound(err))
return
}
assert.NilError(t, err)
@ -117,5 +118,5 @@ func TestStoreGetListDoesNotExist(t *testing.T) {
listRef := ref("list")
_, err := store.GetList(listRef)
assert.Error(t, err, "No such manifest: list")
assert.Check(t, IsNotFound(err))
assert.Check(t, errdefs.IsNotFound(err))
}

View File

@ -3,6 +3,7 @@ package trust
import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
@ -107,6 +108,11 @@ func (scs simpleCredentialStore) RefreshToken(*url.URL, string) string {
func (simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {}
const dctDeprecation = `WARNING: Docker is retiring DCT for Docker Official Images (DOI).
For details, refer to https://docs.docker.com/go/dct-deprecation/
`
// GetNotaryRepository returns a NotaryRepository which stores all the
// information needed to operate on a notary repository.
// It creates an HTTP transport providing authentication support.
@ -115,6 +121,9 @@ func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo
if err != nil {
return nil, err
}
if server == NotaryServer {
_, _ = fmt.Fprint(os.Stderr, dctDeprecation)
}
cfg := tlsconfig.ClientDefault()
cfg.InsecureSkipVerify = !repoInfo.Index.Secure
@ -342,7 +351,10 @@ func GetImageReferencesAndAuth(ctx context.Context,
return ImageRefAndAuth{}, err
}
// Resolve the Repository name from fqn to RepositoryInfo
// Resolve the Repository name from fqn to RepositoryInfo, and create an
// IndexInfo. Docker Content Trust uses the IndexInfo.Official field to
// select the right domain for Docker Hub's Notary server;
// https://github.com/docker/cli/blob/v28.4.0/cli/trust/trust.go#L65-L79
indexInfo := registry.NewIndexInfo(ref)
authConfig := authResolver(ctx, indexInfo)
return ImageRefAndAuth{

View File

@ -1,5 +1,5 @@
variable "GO_VERSION" {
default = "1.24.7"
default = "1.24.9"
}
variable "VERSION" {
default = ""

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.24.7
ARG GO_VERSION=1.24.9
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
@ -28,7 +28,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
FROM golang AS gotestsum
# GOTESTSUM_VERSION sets the version of gotestsum to install in the dev container.
# It must be a valid tag in the https://github.com/gotestyourself/gotestsum repository.
ARG GOTESTSUM_VERSION=v1.12.3
ARG GOTESTSUM_VERSION=v1.13.0
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
--mount=type=tmpfs,target=/go/src/ \

View File

@ -1,12 +1,13 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.24.7
ARG GO_VERSION=1.24.9
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.21
ARG GOLANGCI_LINT_VERSION=v2.1.5
# GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use.
ARG GOLANGCI_LINT_VERSION=v2.5.0
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.24.7
ARG GO_VERSION=1.24.9
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository

View File

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.24.7
ARG GO_VERSION=1.24.9
FROM golang:${GO_VERSION}-alpine AS generated
ENV GOTOOLCHAIN=local

View File

@ -60,6 +60,8 @@ func (opts *ListOpts) Set(value string) error {
}
// Delete removes the specified element from the slice.
//
// Deprecated: this method is no longer used and will be removed in the next release.
func (opts *ListOpts) Delete(key string) {
for i, k := range *opts.values {
if k == key {
@ -264,6 +266,8 @@ func ValidateIPAddress(val string) (string, error) {
}
// ValidateMACAddress validates a MAC address.
//
// Deprecated: use [net.ParseMAC]. This function will be removed in the next release.
func ValidateMACAddress(val string) (string, error) {
_, err := net.ParseMAC(strings.TrimSpace(val))
if err != nil {

View File

@ -142,18 +142,14 @@ func TestListOptsWithoutValidator(t *testing.T) {
if o.Get("baz") {
t.Error(`o.Get("baz") == true`)
}
o.Delete("foo")
if o.String() != "[bar bar]" {
t.Errorf("%s != [bar bar]", o.String())
if listOpts := o.GetSlice(); len(listOpts) != 3 || listOpts[0] != "foo" || listOpts[1] != "bar" || listOpts[2] != "bar" {
t.Errorf("Expected [[foo bar bar]], got [%v]", listOpts)
}
if listOpts := o.GetAll(); len(listOpts) != 2 || listOpts[0] != "bar" || listOpts[1] != "bar" {
t.Errorf("Expected [[bar bar]], got [%v]", listOpts)
if listOpts := o.GetAll(); len(listOpts) != 3 || listOpts[0] != "foo" || listOpts[1] != "bar" || listOpts[2] != "bar" {
t.Errorf("Expected [[foo bar bar]], got [%v]", listOpts)
}
if listOpts := o.GetSlice(); len(listOpts) != 2 || listOpts[0] != "bar" || listOpts[1] != "bar" {
t.Errorf("Expected [[bar bar]], got [%v]", listOpts)
}
if mapListOpts := o.GetMap(); len(mapListOpts) != 1 {
t.Errorf("Expected [map[bar:{}]], got [%v]", mapListOpts)
if mapListOpts := o.GetMap(); len(mapListOpts) != 2 {
t.Errorf("Expected [map[bar:{} foo:{}]], got [%v]", mapListOpts)
}
}
@ -186,9 +182,8 @@ func TestListOptsWithValidator(t *testing.T) {
if o.Get("baz") {
t.Error(`o.Get("baz") == true`)
}
o.Delete("valid-option2=2")
if o.String() != "" {
t.Errorf(`%s != ""`, o.String())
if expected := "[valid-option2=2]"; o.String() != expected {
t.Errorf(`%s != %q`, o.String(), expected)
}
}
@ -396,20 +391,6 @@ func TestNamedMapOpts(t *testing.T) {
}
}
func TestValidateMACAddress(t *testing.T) {
if _, err := ValidateMACAddress(`92:d0:c6:0a:29:33`); err != nil {
t.Fatalf("ValidateMACAddress(`92:d0:c6:0a:29:33`) got %s", err)
}
if _, err := ValidateMACAddress(`92:d0:c6:0a:33`); err == nil {
t.Fatalf("ValidateMACAddress(`92:d0:c6:0a:33`) succeeded; expected failure on invalid MAC")
}
if _, err := ValidateMACAddress(`random invalid string`); err == nil {
t.Fatalf("ValidateMACAddress(`random invalid string`) succeeded; expected failure on invalid MAC")
}
}
func TestValidateLink(t *testing.T) {
valid := []string{
"name",

View File

@ -16,7 +16,7 @@ require (
github.com/distribution/reference v0.6.0
github.com/docker/cli-docs-tool v0.10.0
github.com/docker/distribution v2.8.3+incompatible
github.com/docker/docker v28.4.1-0.20250924162609-d21856f25dbe+incompatible // 28.x branch (v28.5.0+incompatible not yet released)
github.com/docker/docker v28.5.1+incompatible
github.com/docker/docker-credential-helpers v0.9.3
github.com/docker/go-connections v0.6.0
github.com/docker/go-units v0.5.0

View File

@ -57,8 +57,8 @@ github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09f
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.4.1-0.20250924162609-d21856f25dbe+incompatible h1:6aisV+k7ZyODFCKg5HzMbw2fgp5ibtZSKfnUutplsDQ=
github.com/docker/docker v28.4.1-0.20250924162609-d21856f25dbe+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=

View File

@ -81,7 +81,6 @@ info:
{
"username": "string",
"password": "string",
"email": "string",
"serveraddress": "string"
}
```
@ -637,6 +636,9 @@ definitions:
by the default (runc) runtime.
This field is omitted when empty.
**Deprecated**: This field is deprecated as kernel 6.12 has deprecated `memory.kmem.tcp.limit_in_bytes` field
for cgroups v1. This field will be removed in a future release.
type: "integer"
format: "int64"
MemoryReservation:
@ -1936,6 +1938,11 @@ definitions:
Depending on how the image was created, this field may be empty and
is only set for images that were built/created locally. This field
is empty if the image was pulled from an image registry.
> **Deprecated**: This field is only set when using the deprecated
> legacy builder. It is included in API responses for informational
> purposes, but should not be depended on as it will be omitted
> once the legacy builder is removed.
type: "string"
x-nullable: false
example: ""
@ -1961,6 +1968,11 @@ definitions:
The version of Docker that was used to build the image.
Depending on how the image was created, this field may be empty.
> **Deprecated**: This field is only set when using the deprecated
> legacy builder. It is included in API responses for informational
> purposes, but should not be depended on as it will be omitted
> once the legacy builder is removed.
type: "string"
x-nullable: false
example: "27.0.1"
@ -2005,14 +2017,6 @@ definitions:
format: "int64"
x-nullable: false
example: 1239828
VirtualSize:
description: |
Total size of the image including all layers it is composed of.
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
type: "integer"
format: "int64"
example: 1239828
GraphDriver:
$ref: "#/definitions/DriverData"
RootFS:
@ -2145,14 +2149,6 @@ definitions:
format: "int64"
x-nullable: false
example: 1239828
VirtualSize:
description: |-
Total size of the image including all layers it is composed of.
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
type: "integer"
format: "int64"
example: 172064416
Labels:
description: "User-defined key/value metadata."
type: "object"
@ -3146,10 +3142,15 @@ definitions:
- Args
properties:
DockerVersion:
description: "Docker Version used to create the plugin"
description: |-
Docker Version used to create the plugin.
Depending on how the plugin was created, this field may be empty or omitted.
Deprecated: this field is no longer set, and will be removed in the next API version.
type: "string"
x-nullable: false
example: "17.06.0-ce"
x-omitempty: true
Description:
type: "string"
x-nullable: false
@ -6351,6 +6352,8 @@ definitions:
Kernel memory TCP limits are not supported when using cgroups v2, which
does not support the corresponding `memory.kmem.tcp.limit_in_bytes` cgroup.
**Deprecated**: This field is deprecated as kernel 6.12 has deprecated kernel memory TCP accounting.
type: "boolean"
example: true
CpuCfsPeriod:
@ -6388,29 +6391,6 @@ definitions:
description: "Indicates IPv4 forwarding is enabled."
type: "boolean"
example: true
BridgeNfIptables:
description: |
Indicates if `bridge-nf-call-iptables` is available on the host when
the daemon was started.
<p><br /></p>
> **Deprecated**: netfilter module is now loaded on-demand and no longer
> during daemon startup, making this field obsolete. This field is always
> `false` and will be removed in a API v1.49.
type: "boolean"
example: false
BridgeNfIp6tables:
description: |
Indicates if `bridge-nf-call-ip6tables` is available on the host.
<p><br /></p>
> **Deprecated**: netfilter module is now loaded on-demand, and no longer
> during daemon startup, making this field obsolete. This field is always
> `false` and will be removed in a API v1.49.
type: "boolean"
example: false
Debug:
description: |
Indicates if the daemon is running in debug-mode / with debug-level

View File

@ -394,7 +394,12 @@ type Resources struct {
// KernelMemory specifies the kernel memory limit (in bytes) for the container.
// Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes.
KernelMemory int64 `json:",omitempty"`
KernelMemory int64 `json:",omitempty"`
// Hard limit for kernel TCP buffer memory (in bytes).
//
// Deprecated: This field is deprecated and will be removed in the next release.
// Starting with 6.12, the kernel has deprecated kernel memory tcp accounting
// for cgroups v1.
KernelMemoryTCP int64 `json:",omitempty"` // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap

View File

@ -48,6 +48,8 @@ type InspectResponse struct {
// Depending on how the image was created, this field may be empty and
// is only set for images that were built/created locally. This field
// is empty if the image was pulled from an image registry.
//
// Deprecated: this field is deprecated, and will be removed in the next release.
Parent string
// Comment is an optional message that can be set when committing or
@ -80,6 +82,8 @@ type InspectResponse struct {
// DockerVersion is the version of Docker that was used to build the image.
//
// Depending on how the image was created, this field may be empty.
//
// Deprecated: this field is deprecated, and will be removed in the next release.
DockerVersion string
// Author is the name of the author that was specified when committing the

View File

@ -42,7 +42,11 @@ type PluginConfig struct {
// Required: true
Description string `json:"Description"`
// Docker Version used to create the plugin
// Docker Version used to create the plugin.
//
// Depending on how the plugin was created, this field may be empty or omitted.
//
// Deprecated: this field is no longer set, and will be removed in the next API version.
DockerVersion string `json:"DockerVersion,omitempty"`
// documentation

View File

@ -9,19 +9,23 @@ import (
// Info contains response of Engine API:
// GET "/info"
type Info struct {
ID string
Containers int
ContainersRunning int
ContainersPaused int
ContainersStopped int
Images int
Driver string
DriverStatus [][2]string
SystemStatus [][2]string `json:",omitempty"` // SystemStatus is only propagated by the Swarm standalone API
Plugins PluginsInfo
MemoryLimit bool
SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
ID string
Containers int
ContainersRunning int
ContainersPaused int
ContainersStopped int
Images int
Driver string
DriverStatus [][2]string
SystemStatus [][2]string `json:",omitempty"` // SystemStatus is only propagated by the Swarm standalone API
Plugins PluginsInfo
MemoryLimit bool
SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
// KernelMemoryLimit is not supported on cgroups v2.
//
// Deprecated: This field is deprecated and will be removed in the next release.
// Starting with kernel 6.12, the kernel has deprecated kernel memory tcp accounting
KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2.
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"`

2
vendor/modules.txt vendored
View File

@ -65,7 +65,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 v28.4.1-0.20250924162609-d21856f25dbe+incompatible
# github.com/docker/docker v28.5.1+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types