Compare commits

...
125 Commits
Author SHA1 Message Date
Sebastiaan van Stijn 17b57bb493 Merge pull request #7312 from a3ylf/fix/gpu-duplicate-count
opts: Reject duplicate shorthand GPU counts
2026-11-12 15:48:11 +01:00
Sebastiaan van Stijn 71758c77cc Merge pull request #7516 from docker/dependabot/github_actions/docker-actions-aa94fefc13
build(deps): bump docker/github-builder/.github/workflows/bake.yml from 1.18.1 to 1.19.0 in the docker-actions group
2026-11-12 10:13:51 +01:00
dependabot[bot] 5587534468 build(deps): bump docker/github-builder/.github/workflows/bake.yml
Bumps the docker-actions group with 1 update: [docker/github-builder/.github/workflows/bake.yml](https://github.com/docker/github-builder).


Updates `docker/github-builder/.github/workflows/bake.yml` from 1.18.1 to 1.19.0
- [Release notes](https://github.com/docker/github-builder/releases)
- [Commits](https://github.com/docker/github-builder/compare/cbc9d42f8c89a55623392aadd03600965b80e963...a31d2311da4d55e21b978c1c52bab82ba97d51ee)

---
updated-dependencies:
- dependency-name: docker/github-builder/.github/workflows/bake.yml
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docker-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-12 08:42:52 +00:00
Sebastiaan van Stijn 06e6e1db50 Merge pull request #7511 from docker/dependabot/github_actions/codeql-actions-72405e3d5e
build(deps): bump the codeql-actions group with 3 updates
2026-11-11 09:56:14 +01:00
dependabot[bot] 0dfbfa6de0 build(deps): bump the codeql-actions group with 3 updates
Bumps the codeql-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.39.2 to 4.39.3
- [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/1fc58d04a4d4374f921bdac573c3811c240f9c26...33d7b85da1a04171e211befe2c739303b9a4c066)

Updates `github/codeql-action/autobuild` from 4.39.2 to 4.39.3
- [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/1fc58d04a4d4374f921bdac573c3811c240f9c26...33d7b85da1a04171e211befe2c739303b9a4c066)

Updates `github/codeql-action/analyze` from 4.39.2 to 4.39.3
- [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/1fc58d04a4d4374f921bdac573c3811c240f9c26...33d7b85da1a04171e211befe2c739303b9a4c066)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.39.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.39.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.39.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-11 08:42:34 +00:00
Sebastiaan van Stijn e5ef05054c Merge pull request #7507 from thaJeztah/bump_x_deps
vendor: update golang.org/x/* deps
2026-11-10 20:33:00 +01:00
Sebastiaan van Stijn c55feebf74 vendor: golang.org/x/text v0.44.0
- internal/export/idna: avoid excessive work in Punycode encoding
- language: count '_' alongside '-' in ParseAcceptLanguage guard
- go.mod: update golang.org/x dependencies

full diff: https://github.com/golang/text/compare/v0.43.0...v0.44.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-10 20:26:15 +01:00
Sebastiaan van Stijn 83d2f9c986 vendor: golang.org/x/term v0.48.0
no changes in vendored code

- go.mod: update golang.org/x dependencies

full diff: https://github.com/golang/term/compare/v0.47.0...v0.48.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-10 20:25:24 +01:00
Sebastiaan van Stijn bc9b8d9a15 vendor: golang.org/x/mod v0.43.0
no changes in vendored code

full diff: https://github.com/golang/mod/compare/v0.42.0...v0.43.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-10 20:24:26 +01:00
Sebastiaan van Stijn 6758ba62d0 vendor: golang.org/x/sync v0.25.0
full diff: https://github.com/golang/sync/compare/v0.24.0...v0.25.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-10 20:23:34 +01:00
Paweł Gronowski 1894f9a25a Merge pull request #7506 from vvoland/update-go
Update to go1.27.4
2026-11-10 20:16:04 +01:00
Paweł Gronowski 258c9ea25e Update to go1.27.4
This release includes 12 security fixes following the security policy:

- net/http: HTTP/1 server crash due to MaxBytesReader header race

  For HTTP/1 servers, when MaxBytesReader's limit is exceeded,
  "Connection: close" header is automatically set without synchronization,
  which might race with another header being set explicitly in the server
  handler. As a result, an HTTP/1 server that utilizes MaxBytesReader or
  MaxBytesHandler can crash due to runtime panic if its handler reads the
  request body concurrently with writing the response header.

  Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue.

  This is CVE-2026-97054 and Go issue https://go.dev/issue/82563.

- cmd/go: unexpected code execution via --sysroot, -target, -isysroot, -Wl,-syslibroot, and -x cgo flags

  Building a malicious package that uses cgo could cause arbitrary code execution
  at build time through several compiler and linker flags permitted in "#cgo"
  directives.

  Specifically, "--sysroot" in GCC and Clang relocates compiler subprograms, spec
  files, and CRT startup objects to an attacker-controlled directory; "-target" in
  Clang falls back to executing target helper tools from the current working
  directory when not found in PATH; "-isysroot" and "-Wl,-syslibroot" can pass a
  regular file on disk to GNU ld.bfd, which interprets it as a positional linker
  script; and "-x" permitted specifying arbitrary compiler input languages beyond
  those supported by cgo.

  "--sysroot" and "-target" are now disallowed in "#cgo" flags, "-isysroot" and
  "-Wl,-syslibroot" are verified not to point to regular files, and "-x" is
  restricted to the C, C++, Objective-C, and assembler languages supported by cgo.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97033 and Go issue https://go.dev/issue/82577.

- cmd/go: arbitrary command execution via GCC spec files in cgo linker search directories

  When using GCC, building a malicious package that uses cgo could cause arbitrary
  command execution at link time via untrusted GCC spec files ("specs" or
  "*.spec").

  When linking with "-fopenmp", "-fopenacc", or "-fsanitize=" in "#cgo LDFLAGS",
  GCC's built-in link spec evaluates "%:include(libgomp.spec)" or
  "%:include(libsanitizer.spec)" and searches for spec files in "-L" and sysroot
  directories (including subdirectories and multilib sibling directories such as
  "../lib64"), as well as the working directory when "-fopenmp" or "-fopenacc" is
  used or when "-fsanitize=" is combined with "-static" or "-static-lib*".

  The go command now rejects "-L", "-isysroot", and "-Wl,-syslibroot" directories
  (and the working and package directories when applicable) that contain GCC spec
  files, and disallows "@" and "-" prefixes in "-fsanitize=" compiler flag values.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97034 and Go issue https://go.dev/issue/82576.

- cmd/go: unexpected code execution and arbitrary file write via Clang -gen-* and GCC -gnat* flags in cgo

  When using Clang or GCC, building a malicious package that uses cgo could cause
  unexpected code execution at build time or write files to arbitrary
  directories via "-gen-" or "-gnat" flags in "#cgo" directives.

  The "-g*" wildcard in the compiler and linker flag allowlists previously
  matched Clang's two-argument "-gen-cdb-fragment-path " flag and GCC's
  two-argument "-gnatO " flag, permitting compilation database fragments
  and sidecar output files to be written to arbitrary directories and
  desynchronizing flag argument parsing between the go command and the compiler
  driver so that subsequent arguments could be passed as unvalidated positional
  inputs to the linker.

  "-gen-" and "-gnat" flags are now disallowed in "#cgo" compiler and linker
  flags.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97035 and Go issue https://go.dev/issue/82575.

- cmd/go: arbitrary code execution during build on darwin via "-l to_library" in cgo

  On Darwin, building a malicious package that uses cgo could cause arbitrary code
  execution when using the Apple linker due to passing "-l to_library " in a
  "#cgo LDFLAGS" directive.

  The Apple linker recombines the separated arguments "-l" and "to_library" into
  "-lto_library", which loads an arbitrary LTO plugin dynamic library at link
  time.

  The go command now disallows "-l" followed by "to_library" in "#cgo LDFLAGS",
  rejects "-lazy_library", "-lazy_framework", "-load_hidden", "-library", and
  "-library-path", and checks recombined "-l" arguments against disallowed linker
  flags and patterns.

  Thanks to Ali Sherif (https://www.linkedin.com/in/ali-sherif-13812b276/) for reporting this issue.

  This is CVE-2026-97036 and Go issue https://go.dev/issue/82574.

- cmd/go: linker script injection via split -Wl, flags and Darwin or symbol linker flags in cgo

  Building a malicious package that uses cgo could cause arbitrary code execution
  at link time by passing linker script files to the host linker via "#cgo LDFLAGS".

  Split "-Wl," flags that consume a following argument (such as "-Wl,-rpath",
  "-Wl,--just-symbols", and "-Wl,-undefined") previously accepted a bare second
  argument without a "-Wl," prefix, which the compiler driver passes directly to
  the linker as a positional input file. Additionally, when using GNU ld.bfd,
  flags such as "-framework", "-Wl,-framework", "-Wl,-undefined",
  "-Wl,--just-symbols", "-Wl,-R", "-Wl,-subsystem", and (on non-Darwin platforms)
  "-Wl,-sectcreate" could cause ld.bfd to interpret their arguments as linker
  scripts if they named a regular file on disk.

  The go command now requires a "-Wl," prefix on the second token of split "-Wl,"
  flags (except "-Wl,-R"), verifies that these flags do not reference linker
  script files, and disallows bare "-Wl,--warn-backrefs-exclude".

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97037 and Go issue https://go.dev/issue/82573.

- cmd/go: arbitrary code execution via crafted .syso files and cgo linker input files

  Building a malicious package containing ".syso" files or cgo linker inputs could
  inject arbitrary linker flags or execute arbitrary code at link time.

  Linker input files—including ".syso" files, direct object or library inputs in
  "#cgo LDFLAGS", and libraries in "-L" directories—were passed to the external
  linker without validating their format or checking for embedded linker options.
  Across platforms, this allowed executing GNU ld implicit linker scripts
  disguised as libraries or ".syso" files (or loaded via "-l:" or "-l"
  containing path separators), injecting unallowlisted linker flags via PE/COFF
  ".drectve" sections on Windows or Mach-O "LC_LINKER_OPTION" load commands on
  Darwin, or invoking LTO plugins via GCC or LLVM LTO intermediate representation
  sections in ELF, PE/COFF, or Mach-O objects.

  The go command now verifies that ".syso" files, direct linker inputs, and
  libraries in "-L" directories are valid binary objects or archives that do not
  contain unallowlisted ".drectve" directives, "LC_LINKER_OPTION" load commands,
  or LTO IR sections, and disallows "-l:" and ":", "=", or path
  separators in "-l" flags.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97038 and Go issue https://go.dev/issue/82572.

- cmd/go: flag sanitization bypass via "#cgo pkg-config:" directives

  Building a malicious package that uses "#cgo pkg-config:" directives could
  load untrusted pkg-config ".pc" files or inject unvalidated compiler and linker
  flags.

  The pkg-config flag allowlist previously permitted "--with-path=" and
  "--personality=", allowed "--define-variable=" values beginning with "=" or "$"
  (which can rewrite paths in system ".pc" files into sysroot-prefixed "-L=" or
  "-L$SYSROOT" linker search paths), and allowed package arguments ending in ".pc"
  or containing path separators or "..", which caused pkg-config to load local
  ".pc" files directly from the package directory. In addition, flags returned by
  "pkg-config --cflags" in cgoCPPFLAGS were not checked when determining whether
  internal linking is safe.

  The go command now disallows "--with-path=", "--personality=", leading "=" or
  "$" characters in "--define-variable=" values, and local ".pc" paths in
  "#cgo pkg-config:" directives, and inspects cgoCPPFLAGS when checking internal
  linking compatibility.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97039 and Go issue https://go.dev/issue/82571.

- cmd/go, cmd/link: cgo directive injection via .syso files disguised as Go object files

  Building a package containing a crafted ".syso" file could bypass cgo flag
  validation and inject arbitrary linker flags when linking.

  When loading ".syso" entries from a package archive, the linker only checked for
  recognized host object headers (ELF, Mach-O, PE, and XCOFF) before falling
  through to Go object parsing. A ".syso" file beginning with a "go object" header
  was parsed as a Go compiler object, allowing untrusted cgo metadata directives
  (such as "cgo_ldflag" or "cgo_dynamic_linker") embedded in the ".syso" file to
  be passed to the external linker without validation. Additionally, ".syso"
  filenames longer than 16 bytes lost their ".syso" extension when truncated in
  archive headers, and unrecognized ".syso" formats forced external linking in
  pure-Go builds.

  The linker now rejects ".syso" files that are not recognized host object
  formats, and "cmd/go" and "cmd/pack" preserve the ".syso" suffix when truncating
  long archive member names.

  Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue.

  This is CVE-2026-97040 and Go issue https://go.dev/issue/82570.

- cmd/compile, cmd/link: host linker flag injection via //go:cgo_* directives

  Building a malicious package containing "//go:cgo_*" compiler directives could
  inject arbitrary flags into the external linker invocation on ELF platforms.

  The compiler and linker did not reject commas in "//go:cgo_import_dynamic",
  "//go:cgo_export_dynamic", "//go:cgo_export_static", "//go:cgo_import_static",
  and "//go:cgo_dynamic_linker" directives, and the linker passed the dynamic
  linker path using "-Wl,--dynamic-linker,". Furthermore, the two-argument
  form of "//go:cgo_import_dynamic" (which is permitted in non-cgo Go source
  files) could overwrite the external symbol name of a symbol already marked for
  cgo export. A symbol name or dynamic linker path containing a comma or leading
  "@" could split "-Wl,--export-dynamic-symbol=" or "-Wl,--dynamic-linker," into
  arbitrary host linker flags or response file arguments.

  The compiler and linker now reject commas in "//go:cgo_*" symbol and dynamic
  linker directives, the linker passes "-Wl,--dynamic-linker=", and
  "cgo_import_dynamic" no longer overwrites symbols exported via
  "cgo_export_dynamic" or "cgo_export_static".

  Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue.

  This is CVE-2026-97041 and Go issue https://go.dev/issue/82569.

- cmd/cgo, cmd/compile, cmd/link: linker flag injection via cgo_import_dynamic and PE DLL names

  Building a malicious package that uses "//go:cgo_import_dynamic" or links
  against a crafted PE object on Windows could pass unsafe library arguments to
  the external linker.

  The compiler only checked the first character of the library name in
  "//go:cgo_import_dynamic" directives and skipped validation in cgo-generated
  files. In addition, on Windows, "cmd/cgo" and "cmd/link" did not validate
  imported DLL names extracted from PE object files before emitting "-l"
  flags for the external linker, allowing a crafted DLL name containing ".." path
  traversal or special characters to reference arbitrary files on disk.

  The compiler now validates every character of the library name in
  "//go:cgo_import_dynamic" directives (including in cgo-generated files on
  Windows) and rejects ".." path traversal, and "cmd/cgo" and "cmd/link" reject
  PE imported DLL names containing path separators, "..", ":", or leading "-" or
  "@".

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97042 and Go issue https://go.dev/issue/82568.

- cmd/go, cmd/compile: unexpected code execution via escaped quotes in //go:cgo_ldflag

  Building a malicious package that uses cgo could bypass "#cgo LDFLAGS"
  validation and cause unexpected code execution at build time, or cause the go
  command to panic, via crafted quoting in "//go:cgo_ldflag" directives.

  When "cmd/cgo" generates "_cgo_gotypes.go", it quotes each "#cgo LDFLAGS"
  argument with strconv.Quote in a "//go:cgo_ldflag" directive, but "cmd/compile"
  and "cmd/go" parsed those directives by splitting on raw quote characters
  without handling backslash escapes or unquoting the string. This mismatch
  allowed disallowed linker flags or unvalidated linker search paths to be
  smuggled past the go command's flag checks and passed to the external linker.
  In addition, deduplicating LDFLAGS in the go command could panic with an
  out-of-bounds slice index when a prefix of the flag list matched near the end
  of the slice.

  "cmd/compile" and "cmd/go" now properly handle backslash-escaped quotes and
  unquote "//go:cgo_*" pragma strings with strconv.Unquote, and the slice bounds
  check in processCgoOutputs has been fixed.

  This issue was found by the Go Security Team during an internal audit.

  This is CVE-2026-97043 and Go issue https://go.dev/issue/82567.

release notes: https://go.dev/doc/devel/release#go1.27.4

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-11-10 19:54:00 +01:00
Sebastiaan van Stijn 2cc835a842 Merge pull request #7495 from azchohfi/otel-no-retry
cli/command: disable retries for the OTLP exporters
2026-11-10 19:48:54 +01:00
Sebastiaan van Stijn e9fa001901 Merge pull request #7505 from thaJeztah/bump_x_sys
vendor: golang.org/x/sys v0.50.0
2026-11-10 16:01:18 +01:00
Sebastiaan van Stijn 3399deb9e7 vendor: golang.org/x/sys v0.50.0
full diff: https://github.com/golang/sys/compare/f5cb0306ac0e...v0.50.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-10 15:48:48 +01:00
Sebastiaan van Stijn 5dce5cf00a Merge pull request #7494 from renovate-bot/renovate/docker-buildx-bin-0.x
chore(deps): update docker/buildx-bin docker tag to v0.38.2
2026-11-10 15:45:55 +01:00
Sebastiaan van Stijn 26f11944b9 Merge pull request #7504 from renovate-bot/renovate/github-codeql-action-4.x
chore(deps): update github/codeql-action action to v4.39.2
2026-11-10 15:44:39 +01:00
Mend Renovate 2914f034fa chore(deps): update github/codeql-action action to v4.39.2
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-10 14:38:41 +00:00
Alexandre Zollinger ChohfiandCopilot App a5d7547c39 cli/command: disable retries for the OTLP exporters
The CLI flushes traces and metrics at exit with a 50ms timeout
(ExportTimeout). The OTLP gRPC exporters were created with the default
retry policy, so when the endpoint refuses the connection the export
keeps backing off until the timeout expires instead of returning.

This happens on every command when the current context points at a
unix socket that has no listener, for example Docker Desktop's context
while Desktop is not running, which leaves its analytics socket file
behind. A retry cannot complete within 50ms anyway, so turn retries off.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Alexandre Zollinger Chohfi <alzollin@microsoft.com>
2026-11-06 11:00:59 -08:00
Mend Renovate 532b10a36f chore(deps): update docker/buildx-bin docker tag to v0.38.2
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-06 18:57:10 +00:00
Paweł Gronowski 7c0f1b261a Merge pull request #7493 from vvoland/update-docker
vendor: github.com/moby/moby master
2026-11-06 02:29:17 +01:00
Paweł Gronowski e863f84b15 vendor: github.com/moby/moby/client v0.7.0-dev (402d0a16f131)
full diff: https://github.com/moby/moby/compare/client/v0.6.2...402d0a16f131

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-11-06 02:23:19 +01:00
Paweł Gronowski e969249cf5 vendor: github.com/moby/moby/api v1.57.0-dev (402d0a16f131)
full diff: https://github.com/moby/moby/compare/api/v1.56.1...402d0a16f131

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-11-06 02:21:44 +01:00
Paweł Gronowski bad50f6bbe Merge pull request #7492 from thaJeztah/bump_capability
vendor: github.com/moby/sys/capability v0.5.0
2026-11-06 01:14:22 +01:00
Sebastiaan van Stijn 89e99a7ee4 Merge pull request #7393 from renovate-bot/renovate/psampaz-go-mod-outdated-0.x
chore(deps): update psampaz/go-mod-outdated docker tag to v0.9.0
2026-11-06 00:37:20 +01:00
Sebastiaan van Stijn e63c04ae28 vendor: github.com/moby/sys/capability v0.5.0
full diff: https://github.com/moby/sys/compare/capability/v0.4.0...capability/v0.5.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-06 00:23:28 +01:00
Sebastiaan van Stijn c3a866740e Merge pull request #7488 from thaJeztah/docs_trixie
docs: update example versions of debian an ubuntu
2026-11-06 00:05:21 +01:00
Sebastiaan van Stijn dfe5bf3073 Merge pull request #7489 from thaJeztah/bump_go127
update to go1.27.3
2026-11-05 23:59:05 +01:00
Sebastiaan van Stijn 85af295d30 update to go1.27.3
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:47:28 +01:00
Sebastiaan van Stijn de692998a4 Merge pull request #7490 from thaJeztah/bump_x_sys
vendor: golang.org/x/sys f5cb0306ac0e (fix for go1.27)
2026-11-05 23:46:40 +01:00
Sebastiaan van Stijn 873db34f4b Merge pull request #7491 from thaJeztah/bump_golangci
update to golangci-lint 2.14 (for go1.27)
2026-11-05 23:46:11 +01:00
Sebastiaan van Stijn 66da404208 Merge pull request #7486 from thaJeztah/bump_trixie
update to debian trixie
2026-11-05 23:39:05 +01:00
Sebastiaan van Stijn a0f7df60ba update to debian trixie
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:29:15 +01:00
Sebastiaan van Stijn 8fa64e724a vendor: golang.org/x/sys f5cb0306ac0e (fix for go1.27)
includes a fix for https://go.dev/issue/82324

full diff: https://github.com/golang/sys/compare/v0.49.0...f5cb0306ac0e4b93b83ddd53c36d6693af3214e3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:23:39 +01:00
Sebastiaan van Stijn e2aefc6e1a docs: update examples for ubuntu LTS versions
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:19:42 +01:00
Sebastiaan van Stijn 26a4786788 update to golangci-lint 2.14 (for go1.27)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:13:02 +01:00
Sebastiaan van Stijn 8f1203743d fix linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 23:12:57 +01:00
Mend Renovate 32a838bf17 chore(deps): update psampaz/go-mod-outdated docker tag to v0.9.0
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-05 21:28:50 +00:00
Paweł Gronowski cbb0dabae0 Merge pull request #7485 from thaJeztah/bump_alpine
update to alpine 3.24
2026-11-05 22:27:33 +01:00
Paweł Gronowski d216e46795 Merge pull request #7487 from thaJeztah/update_runners
ci: replace retired macOS 14 runner with macOS 26
2026-11-05 22:27:15 +01:00
Sebastiaan van Stijn 1c6c7ffcc8 docs: update examples to use debian trixie
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 22:24:31 +01:00
Sebastiaan van Stijn 11626f30d0 ci: replace retired macOS 14 runner with macOS 26
GitHub Actions retired macOS 14 runners on November 2, 2026.
Replace macos-14 with macos-26 to continue testing on supported
macOS versions.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 22:12:03 +01:00
Sebastiaan van Stijn 7817ee1c5c update to alpine 3.24
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 22:02:33 +01:00
Sebastiaan van Stijn 6b88c47537 Merge pull request #7480 from thaJeztah/bump_ansiterm
vendor: github.com/Azure/go-ansiterm 51075c6ea6bc
2026-11-05 21:28:03 +01:00
Sebastiaan van Stijn 2b3688febb Merge pull request #7481 from dperny/fix-container-names-fallback
cli/command/formatter: restore fallback for container names with slashes
2026-11-05 20:13:15 +01:00
Sebastiaan van Stijn 28f460abf3 Merge pull request #7483 from renovate-bot/renovate/docker-compose-bin-5.x
chore(deps): update docker/compose-bin docker tag to v5.7.0
2026-11-05 19:48:39 +01:00
Mend Renovate 1f6f73a7be chore(deps): update docker/compose-bin docker tag to v5.7.0
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-05 16:52:38 +00:00
Sebastiaan van Stijn f9ad558f5d Merge pull request #7482 from nicksieger/nicksieger/fix-help-run
fix: propagate leading --help to subcommands with a local help flag
2026-11-05 17:49:18 +01:00
Sebastiaan van Stijn dd422f424c Merge pull request #7433 from jsternberg/trace-and-metrics-shutdown
cli-plugins/plugin: add OnFinalize hook for shutting down otel providers
2026-11-05 17:48:40 +01:00
Nick Sieger 965590b378 fix: propagate leading --help to subcommands with a local help flag
- --help before a subcommand is parsed as the root's persistent flag and
  stripped from args, which works for most subcommands since they share
  the same flag object with root
- run/create register their own local help flag (no -h, to avoid a
  shorthand clash with --hostname), which shadows root's and never saw
  the value, so the container ran instead of printing usage
- propagate the parsed value into a subcommand's local help flag when
  one shadows the root's, in HandleGlobalFlags

Fixes #7473

Signed-off-by: Nick Sieger <nick@nicksieger.com>
2026-11-05 09:52:46 -06:00
Drew ErnyandClaude Opus 5.5 191aab9fe8 cli/command/formatter: restore fallback for container names with slashes
Since commit f7a909d56b, ContainerContext.Names returns an empty string
when truncating and every name of the container contains a slash. Before
that change, all names were printed in that case.

Classic Swarm prefixes container names with the node-name
("/<node-name>/<container-name>"), so `docker ps` against a classic Swarm
API printed an empty NAMES column.

Restore the fallback to printing all names when no name without slashes
is found.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Drew Erny <derny@mirantis.com>
2026-11-05 08:53:09 -06:00
Sebastiaan van Stijn 682373a887 vendor: github.com/Azure/go-ansiterm 51075c6ea6bc
full diff: https://github.com/Azure/go-ansiterm/compare/8c912ac31dd4...51075c6ea6bc

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 13:44:53 +01:00
Sebastiaan van Stijn 949b412ae3 Merge pull request #7478 from thaJeztah/codecov_oidc_step2
ci: use OIDC authentication for Codecov uploads (remaining workflows)
2026-11-05 11:27:55 +01:00
Sebastiaan van Stijn 57393ea18e ci: use OIDC authentication for Codecov uploads (remaining workflows)
follow-up to 18958e4c02, which updated
the e2e workflow, but forgot to update the other workflows.

Replace the CODECOV_TOKEN secret with GitHub Actions OIDC authentication.

Codecov supports tokenless uploads for public repositories, but
authenticated uploads are still needed to protect coverage results on
protected branches from unauthorized uploads.

Grant `id-token: write` at the job level to allow Codecov to request
a short-lived OIDC token. This permission does not grant repository
write access, and scoping it to the job avoids granting it to other
jobs added to the workflow in the future.

Coverage uploads from forked pull requests continue to use Codecov's
tokenless upload mechanism.

See https://github.com/codecov/codecov-action/blob/v7.1.1/README.md#using-oidc

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 10:54:27 +01:00
Sebastiaan van Stijn 84e55d46d7 Merge pull request #7477 from thaJeztah/codecov_oidc
ci: use OIDC authentication for Codecov uploads
2026-11-05 10:39:45 +01:00
Sebastiaan van Stijn 18958e4c02 ci: use OIDC authentication for Codecov uploads
Replace the CODECOV_TOKEN secret with GitHub Actions OIDC authentication.

Codecov supports tokenless uploads for public repositories, but
authenticated uploads are still needed to protect coverage results on
protected branches from unauthorized uploads.

Grant `id-token: write` at the job level to allow Codecov to request
a short-lived OIDC token. This permission does not grant repository
write access, and scoping it to the job avoids granting it to other
jobs added to the workflow in the future.

Coverage uploads from forked pull requests continue to use Codecov's
tokenless upload mechanism.

See https://github.com/codecov/codecov-action/blob/v7.1.1/README.md#using-oidc

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-05 10:22:53 +01:00
Sebastiaan van Stijn ab54f1f097 Merge pull request #7168 from hirehamir/fix/flaky-test-prune-prompt-termination
fix: flaky `TestPrunePromptTermination` test
2026-11-05 09:04:07 +01:00
Jonathan A. Sternberg d278c1ec68 cli-plugins/plugin: add OnFinalize hook for shutting down otel providers
OTEL providers provided by this library to plugins were not properly
shut down. Metrics from the CLI were forcibly flushed in a separate area
and the `buildx` command does its own flushing, but this didn't apply to
traces.

Add shutdown on post run for plugins using `OnFinalize`. This will allow
compose to use the tracer provider from this library rather than roll
its own custom one.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2026-11-04 12:45:18 -06:00
Sebastiaan van Stijn fb2fe0eac7 Merge pull request #7468 from thaJeztah/bump_otels
vendor: go.opentelemetry.io/otel v1.47.0, contrib v0.72.0
2026-11-03 22:57:33 +01:00
Paweł Gronowski 920919bd15 Merge pull request #7469 from thaJeztah/bump_compress
vendor: github.com/klauspost/compress v1.20.2 (security)
2026-11-03 22:33:58 +01:00
Paweł Gronowski beafae2696 Merge pull request #7442 from thaJeztah/bump_creds_helpers
vendor: github.com/docker/docker-credential-helpers v0.9.12
2026-11-03 22:30:04 +01:00
Sebastiaan van Stijn b9456fd725 vendor: github.com/klauspost/compress v1.20.2
includes a fix for CVE-2026-116591 / [GHSA-fpmh-frq8-7rj8]

full diff: https://github.com/klauspost/compress/compare/v1.20.1...v1.20.2

[GHSA-fpmh-frq8-7rj8]: https://github.com/klauspost/compress/security/advisories/GHSA-fpmh-frq8-7rj8

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 22:27:00 +01:00
Sebastiaan van Stijn 7a75f75b96 vendor: go.opentelemetry.io/otel v1.47.0, contrib v0.72.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 22:23:13 +01:00
Paweł Gronowski 9762c1688f Merge pull request #7449 from thaJeztah/manifest_completion
manifest: annotate: add shell-completion for --os and --arch
2026-11-03 21:53:15 +01:00
Sebastiaan van Stijn b2f5d905c7 Merge pull request #7466 from thaJeztah/bump_swarmkit
vendor: github.com/moby/swarmkit/v2 v2.1.3
2026-11-03 21:20:00 +01:00
Sebastiaan van Stijn 77ebef3df8 vendor: github.com/moby/swarmkit/v2 v2.1.3
full diff: https://github.com/moby/swarmkit/compare/v2.1.2...v2.1.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 21:11:01 +01:00
Paweł Gronowski 6d15cedd97 Merge pull request #7465 from thaJeztah/bump_x_net
vendor: golang.org/x/net v0.62.0
2026-11-03 17:57:57 +01:00
Sebastiaan van Stijn 82b833e57a vendor: golang.org/x/net v0.62.0
full diff: https://github.com/golang/net/compare/v0.61.0...v0.62.0

This release addresss the following security issues:

- html: avoid quadratic complexity when coalescing text nodes

    When coalescing adjacent text nodes in addText and fosterParent,
    appending to an existing TextNode's Data via string concatenation
    (n.Data += text) reallocated and copied the accumulated string on every
    token. Inputs containing many short text runs separated by ignored end
    tags (such as "a") caused O(n^2) allocations and byte copies.

    Accumulate coalesced text in per-node byte slices during parsing and
    materialize Data strings once at the end of parse.

    Thanks to Markus Magnuson for reporting this issue.

    This is CVE-2026-78661 and Go issue https://go.dev/issue/82224.

- html: check all ancestor namespace transitions when rendering raw text

    In childTextNodesAreLiteral, walking up the tree previously stopped at
    the nearest foreign ancestor once an HTML integration point was found.
    However, that integration point may itself be a descendant of an element
    that was foster-parented into a foreign namespace (such as or
    fostered under ), causing a parser to resolve the
    subtree in a different foreign namespace upon re-parsing the rendered
    output.

    Continue walking the full ancestor chain and verify that every
    transition from a non-empty namespace occurs at an HTML integration
    point before emitting literal text.

    Thanks to Ali Sherif (https://www.linkedin.com/in/ali-sherif-13812b276) for reporting this issue.

    This is CVE-2026-97045 and Go issue https://go.dev/issue/82622.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 14:55:15 +01:00
Paweł Gronowski 997674f459 Merge pull request #7462 from thaJeztah/bump_jose2
vendor: github.com/go-jose/go-jose/v4 v4.1.7 (security)
2026-11-03 14:41:36 +01:00
Sebastiaan van Stijn 81e4a109a3 vendor: github.com/go-jose/go-jose/v4 v4.1.7
Fixed Security Issues

- Thumbprint: reject invalid RSA key [GHSA-r39w-98wm-9pp6]
- json: backport stdlib fix for embedded unexported field [GHSA-27pc-rm86-68pq]
- Detect if headers are set by presence in the map [GHSA-p9j4-2j95-j4rv]
- limit RSA size in certificate verify [GHSA-v6h2-qj3f-2h6v]
- Limit recipients and signatures in JWE/JWS [GHSA-c67m-wr4h-2ccg]

Fixed

- jwk: fix bug in x5c parsing
- reject base64-encoded "null" in protected headers

Deprecated

- deprecate ParseEncrypted / ParseSigned

full diff: https://github.com/go-jose/go-jose/compare/v4.1.6...v4.1.7

[GHSA-r39w-98wm-9pp6]: https://github.com/go-jose/go-jose/security/advisories/GHSA-r39w-98wm-9pp6
[GHSA-27pc-rm86-68pq]: https://github.com/go-jose/go-jose/security/advisories/GHSA-27pc-rm86-68pq
[GHSA-p9j4-2j95-j4rv]: https://github.com/go-jose/go-jose/security/advisories/GHSA-p9j4-2j95-j4rv
[GHSA-v6h2-qj3f-2h6v]: https://github.com/go-jose/go-jose/security/advisories/GHSA-v6h2-qj3f-2h6v
[GHSA-c67m-wr4h-2ccg]: https://github.com/go-jose/go-jose/security/advisories/GHSA-c67m-wr4h-2ccg

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 14:24:18 +01:00
Paweł Gronowski e7ece565b2 Merge pull request #7460 from thaJeztah/bump_yaml
vendor: go.yaml.in/yaml/v3 v3.0.6 (security)
2026-11-03 14:20:18 +01:00
Paweł Gronowski 4214721b3b Merge pull request #7443 from thaJeztah/bump_jose
vendor: github.com/go-jose/go-jose/v4 v4.1.6 (security)
2026-11-03 14:20:05 +01:00
Sebastiaan van Stijn 281291299e Merge pull request #7459 from renovate-bot/renovate/docker-compose-bin-5.x
chore(deps): update docker/compose-bin docker tag to v5.6.1
2026-11-03 12:01:01 +01:00
Sebastiaan van Stijn 796f9633b4 vendor: go.yaml.in/yaml/v3 v3.0.6
resolve: hint-class literal merge-key string "<<" so it's quoted on encode

full diff: https://github.com/yaml/go-yaml/compare/v3.0.5...v3.0.6

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 11:54:24 +01:00
Mend Renovate 29b22240bc chore(deps): update docker/compose-bin docker tag to v5.6.1
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-03 10:45:47 +00:00
Sebastiaan van Stijn 19a353f2ea Merge pull request #7452 from renovate-bot/renovate/docker-buildx-bin-0.x
chore(deps): update docker/buildx-bin docker tag to v0.38.1
2026-11-03 11:44:17 +01:00
Mend Renovate 3bc38f9c19 chore(deps): update docker/buildx-bin docker tag to v0.38.1
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-11-02 14:10:44 +00:00
Sebastiaan van Stijn 0ccbdf86a0 Merge pull request #7430 from docker/dependabot/github_actions/codeql-actions-da882c3ad8
build(deps): bump the codeql-actions group across 1 directory with 3 updates
2026-11-02 15:09:43 +01:00
Sebastiaan van Stijn fbafb4965c Merge pull request #7441 from docker/dependabot/github_actions/docker-actions-1541f28a00
build(deps): bump the docker-actions group across 1 directory with 2 updates
2026-11-02 15:08:48 +01:00
dependabot[bot] 276829e744 build(deps): bump the codeql-actions group across 1 directory with 3 updates
Bumps the codeql-actions group with 3 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.38.3 to 4.39.1
- [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/24c54180a607b1449ed407dd24f251e4e9147c8d...9b3254085494b55a0f7c4c2b3d2d52cc712ce370)

Updates `github/codeql-action/autobuild` from 4.38.3 to 4.39.1
- [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/24c54180a607b1449ed407dd24f251e4e9147c8d...9b3254085494b55a0f7c4c2b3d2d52cc712ce370)

Updates `github/codeql-action/analyze` from 4.38.3 to 4.39.1
- [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/24c54180a607b1449ed407dd24f251e4e9147c8d...9b3254085494b55a0f7c4c2b3d2d52cc712ce370)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-02 08:46:14 +00:00
dependabot[bot] cc8c87844d build(deps): bump the docker-actions group across 1 directory with 2 updates
Bumps the docker-actions group with 2 updates in the / directory: [docker/github-builder/.github/workflows/bake.yml](https://github.com/docker/github-builder) and [docker/docker-agent-action/.github/workflows/review-pr.yml](https://github.com/docker/docker-agent-action).


Updates `docker/github-builder/.github/workflows/bake.yml` from 1.18.0 to 1.18.1
- [Release notes](https://github.com/docker/github-builder/releases)
- [Commits](https://github.com/docker/github-builder/compare/4345a1cea1e4cfb65c8a5e2b1b80f9e630068827...cbc9d42f8c89a55623392aadd03600965b80e963)

Updates `docker/docker-agent-action/.github/workflows/review-pr.yml` from 2.0.9 to 2.1.0
- [Release notes](https://github.com/docker/docker-agent-action/releases)
- [Commits](https://github.com/docker/docker-agent-action/compare/3654ec391b070e247de2e2e3c1ff2519b6378b3a...aaa657c53cc69ed15683cd8a985d86663a0e1594)

---
updated-dependencies:
- dependency-name: docker/docker-agent-action/.github/workflows/review-pr.yml
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docker-actions
- dependency-name: docker/github-builder/.github/workflows/bake.yml
  dependency-version: 1.18.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-02 08:43:09 +00:00
Sebastiaan van Stijn e512522843 manifest: annotate: add shell-completion for --os and --arch
With this patch;

    docker manifest annotate --os <TAB>
    aix        darwin     freebsd    illumos    js         nacl       openbsd    solaris    zos
    android    dragonfly  hurd       ios        linux      netbsd     plan9      windows

    docker manifest annotate --arch <TAB>
    386          arm          armbe        mips64       mips64p32le  ppc64        riscv64      sparc
    amd64        arm64        loong64      mips64le     mipsle       ppc64le      s390         sparc64
    amd64p32     arm64be      mips         mips64p32    ppc          riscv        s390x        wasm

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-30 15:03:10 +01:00
Sebastiaan van Stijn 8c8a77521a Merge pull request #7448 from thaJeztah/carry_7447
manifest: add loong64 to manifest annotate, and remove hard-coded os/arch list in validation
2026-10-30 14:59:17 +01:00
Sebastiaan van Stijn bf8066ca18 manifest: remove hard-coded os/arch list in validation
Replace the hardcoded list of supported OS/architecture combinations with
syntax validation using containerd/platforms.

This allows annotating manifests with platforms that are not explicitly
known to the CLI, while still rejecting missing or malformed values.

The validation uses a FormatAll/Parse roundtrip until containerd/platforms
provides a dedicated validation function.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-30 13:12:26 +01:00
吴小白 d35139c89f manifest: add loong64 to manifest annotate bash completion
Signed-off-by: 吴小白 <296015668@qq.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-30 11:25:59 +01:00
Sebastiaan van Stijn b32aa42608 Merge pull request #7445 from thaJeztah/geen_kabouters
scripts/build: omit DWARF debug information by default
2026-10-29 21:33:03 +01:00
Sebastiaan van Stijn 8ff6f243a2 scripts/build: omit DWARF debug information by default
Pass -w to the Go linker to reduce binary size while retaining the
symbol table for tools that inspect Go binaries.

For a linux/arm64 build, this reduces the CLI binary from 39,809,791
to 31,310,197 bytes: a saving of 8.5 MB (21.4%).

Place the default before caller-supplied GO_LDFLAGS so builds can
retain DWARF by passing GO_LDFLAGS="-w=0".

Before

    ls -l /go/src/github.com/docker/cli/build/docker-linux-arm64
    -rwxr-xr-x 1 root root 39809791 Oct 29 17:34 /go/src/github.com/docker/cli/build/docker-linux-arm64

After

    ls -l /go/src/github.com/docker/cli/build/docker-linux-arm64
    -rwxr-xr-x 1 root root 31310197 Oct 29 17:36 /go/src/github.com/docker/cli/build/docker-linux-arm64

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-29 19:06:26 +01:00
Sebastiaan van Stijn b9312b9d88 scripts/build: suppress shellcheck linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-29 18:29:37 +01:00
Sebastiaan van Stijn ccccec73b0 vendor: github.com/go-jose/go-jose/v4 v4.1.6
- contains a fix for CVE-2026-116587 / [GHSA-mgcc-cww5-fp2q]

full diff: https://github.com/go-jose/go-jose/compare/v4.1.5...v4.1.6

[GHSA-mgcc-cww5-fp2q]: https://github.com/go-jose/go-jose/security/advisories/GHSA-mgcc-cww5-fp2q

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-28 22:38:48 +01:00
Sebastiaan van Stijn dd8edb6863 vendor: github.com/docker/docker-credential-helpers v0.9.12
no changes in vendored code

full diff: https://github.com/docker/docker-credential-helpers/compare/v0.9.9...v0.9.12

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-28 14:23:04 +01:00
Sebastiaan van Stijn 66786b775a Merge pull request #7421 from thaJeztah/bump_x_deps
vendor: update golang.org/x/* dependencies
2026-10-27 10:20:11 +01:00
Paweł Gronowski 47e9dbf7b0 Merge pull request #7427 from renovate-bot/renovate/docker-actions
Update docker GitHub Actions
2026-10-26 20:12:30 +01:00
Mend Renovate abf2f34c74 Update docker GitHub Actions
Signed-off-by: Mend Renovate <bot@renovateapp.com>
2026-10-26 12:59:35 +00:00
Hamir dd50814004 fix: flaky TestPrunePromptTermination test
TerminatePrompt created a pipe for the prompt's stdin but discarded the
write end. Once the garbage collector finalized it, the write end was
closed, the prompt read EOF and treated it as "no", and the command
returned "prune has been cancelled" instead of prompt.ErrTerminated.

This keeps both ends of the pipe referenced and closes them in t.Cleanup.

This change also drops the OutBuffer().Len() check:
the writer hook only fires after
the write has completed, so the check proved nothing, and it raced with
the prompt's later writes under -race.

This change also applies the same fix to the identical copy in cmd/docker-trust.

Signed-off-by: Hamir <hirehamir@gmail.com>
2026-10-22 10:04:59 -07:00
Sebastiaan van Stijn 6d274590f2 Merge pull request #7414 from thaJeztah/interactive_login_nits
internal/oauth: assorted fixes and cleanups
2026-10-20 14:40:35 +02:00
Sebastiaan van Stijn 6998c79cfd vendor: golang.org/x/net v0.61.0
- quic: properly check for allowed frame types in a packet

full diff: https://github.com/golang/net/compare/v0.60.0...v0.61.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:41:27 +02:00
Sebastiaan van Stijn c7bdacad70 vendor: golang.org/x/text v0.43.0
- secure/bidirule: lazily precompute ASCII table
- unicode/bidi: avoid quadratic behavior in Paragraph.Order and Paragraph.Line

full diff: https://github.com/golang/text/compare/v0.42.0...v0.43.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:40:24 +02:00
Sebastiaan van Stijn 1faf23e25f vendor: golang.org/x/term v0.47.0
full diff: https://github.com/golang/term/compare/v0.46.0...v0.47.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:39:46 +02:00
Sebastiaan van Stijn b8dd18fe2c vendor: golang.org/x/sync v0.24.0
full diff: https://github.com/golang/sync/compare/v0.23.0...v0.24.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:39:09 +02:00
Sebastiaan van Stijn a3539bd5c9 vendor: golang.org/x/mod v0.42.0
full diff: https://github.com/golang/mod/compare/v0.41.0...v0.42.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:38:32 +02:00
Sebastiaan van Stijn adfb114576 vendor: golang.org/x/sys v0.49.0
- cpu: add amd64 v2/v3/v4 feature bits
- darwin: expose setpriority PRIO_DARWIN_* constants
- unix/darwin: add missing pwritev test case on darwin/arm64
- unix/darwin: add O_EXEC and O_SEARCH on darwin
- unix/darwin: pass fcntl data as unsafe.Pointer in FcntlF{lock,store} on darwin
- unix/linux: don't warn about closed stderr from child process
- unix/linux: unify ppc64x syscall wrappers
- unix: add listns syscall introduced in Linux 6.19
- unix: add Mmsghdr for linux
- unix: add PrctlArg5Ptr
- unix: align the getdents buffer
- unix: extend z/OS support
- unix: keep generated types compilable with current cgo
- unix: pass xattr data as unsafe.Pointer in BSD xattr syscalls
- unix: provide linux/sparc64 assembly for syscalls
- unix: return syscall error in *listxattrNS on BSD
- unix: update glibc to 2.44
- unix: update linux to v7.2
- unix: use the stat64 family and fix Stat_t on linux/sparc64
- windows: drop arm

full diff: https://github.com/golang/sys/compare/v0.48.0...v0.49.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 13:37:40 +02:00
Sebastiaan van Stijn 4e09976ddd Merge pull request #7419 from thaJeztah/bump_sortorder
vendor: github.com/fvbommel/sortorder v1.2.1
2026-10-20 13:23:25 +02:00
Sebastiaan van Stijn 69c9ccd358 Merge pull request #7417 from vvoland/update-go
Update to go1.26.10
2026-10-20 13:11:47 +02:00
Sebastiaan van Stijn 1600418944 vendor: github.com/fvbommel/sortorder v1.2.1
full diff: https://github.com/fvbommel/sortorder/compare/v1.2.0...v1.2.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-20 12:46:38 +02:00
Paweł Gronowski 1fab379bcc Update to go1.26.10
This release includes 1 security fix following the security policy:

- crypto/x509: mitigation for security concerns with a specific Certificate Authority

  We're blocking trust in a small set of intermediate certificates due to specific security concerns around their operation.

  Verify will now filter out chains which contain these intermediates, preventing them from being returned to the caller.

  We highly recommend immediately upgrading to this release.

  This is CVE-2026-111943 and Go issue https://go.dev/issue/82345.

release notes: https://go.dev/doc/devel/release#go1.26.10

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-20 12:35:48 +02:00
Sebastiaan van Stijn df9a0f430f internal/oauth: remove debug logs, and move them to the caller
Wrap errors in the OAuth manager instead of logging them, preserving
the underlying cause while allowing callers to detect startup failures.

Log failures at the fallback handler and scope the device-code login
result to its branch.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-19 21:07:33 +02:00
Sebastiaan van Stijn fa65e9a3a0 internal/oauth: cleanup output
- Remove extra newline before message
- Include the token in the URL (instead of requiring the user to manually
  enter it on the website).
- Improve the "call to action"; ENTER can be used to automatically open
  the browser (but the user can manually open it instead), and CTRL-C can
  be used to cancel the login.
- Remove the "Waiting for authentication in the browser…" message, which
  could be confusing if no browser was opened (yet), instead print a message
  after successfully requesting the browser to be opened.

When running `docker login`;

    docker login

    i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'

    Your one-time device confirmation code is: NRJL-BLRL
    Open this URL to authenticate: https://login.docker.com/activate?user_code=NRJL-BLRL

    Press ENTER to open the URL in your browser, or Ctrl+C to cancel.

After pressing `ENTER`, it either prints the "success" message;

    Press ENTER to open the URL in your browser, or Ctrl+C to cancel.

    Opening browser…

or a failure when unable to launch a browser;

    Press ENTER to open the URL in your browser, or Ctrl+C to cancel.

    No browser found. Open the URL above manually to continue.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-19 21:07:27 +02:00
Sebastiaan van Stijn dc66c2a8d0 internal/oauth: handle error when failing to open browser
Before this patch, pressing `ENTER` to open the browser would silently
discard the error;

    docker login

    i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'

    Your one-time device confirmation code is: VGTB-VKBG
    Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate

    Waiting for authentication in the browser…

With this patch, a failure is printed, so that the user can manually open
the URL (or cancel the login);

    docker login

    i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'

    Your one-time device confirmation code is: SZFX-BSGP
    Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate

    Waiting for authentication in the browser…

    No browser found. Open the URL above manually to continue.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-19 21:05:24 +02:00
Sebastiaan van Stijn ae317ab44a internal/oauth: combine "web-based login" message with info note
Make the output less verbose, and combine the "web-based login" message
with the info message that's already printed.

Before this patch:

    docker login

    USING WEB-BASED LOGIN

    i Info → To sign in with credentials on the command line, use 'docker login -u <username>'

    Your one-time device confirmation code is: VVPV-NSSL
    Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate

    Waiting for authentication in the browser…

With this patch:

    docker login

    i Info → Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'

    Your one-time device confirmation code is: QBBD-PQNS
    Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate

    Waiting for authentication in the browser…

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-19 21:05:18 +02:00
Sebastiaan van Stijn 3f2ad8bf05 internal/oauth: avoid opening browser after login cancellation
Check the context after reading stdin to avoid launching the browser
if login was canceled while waiting for ENTER.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-19 20:49:29 +02:00
Paweł Gronowski 6f8369014a Merge pull request #7408 from GitNimay/3833-unknown-command-version-flag
cmd/docker: fail on unknown command with --version
2026-10-19 17:06:27 +02:00
Nimesh Kulkarni e08aa72569 cmd/docker: fail on unknown command with --version
Running "docker nonexistent --version" printed the CLI version and
exited 0, so it couldn't be used to check whether a command or plugin
is available. Without "--version" the same invocation fails with an
"unknown command" error.

When no built-in command or plugin matches, runDocker falls through to
executing the root command, and cobra handles the "--version" flag
before the root command reports the unknown command. Unset the root
command's version in that fallback, so the standard unknown-command
error is returned.

A global "--version" flag ("docker --version nonexistent") is parsed
before the command name and still prints the version, as do
"docker --version" and "docker nonexistent --help".

Signed-off-by: Nimesh Kulkarni <167794819+GitNimay@users.noreply.github.com>
2026-10-19 19:35:05 +05:30
Paweł Gronowski f522fffe52 Merge pull request #7412 from vvoland/trust-clean
cmd/docker-trust: Inline some cli dependencies
2026-10-19 14:32:57 +02:00
Paweł Gronowski 5e1e84ee5d cmd/docker-trust: Use standard regexps for name validation
The plugin only used lazyregexp for two small, fixed name patterns.
Replaced it with regexp.MustCompile without changing validation.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-19 13:28:28 +02:00
Paweł Gronowski 00bf2d970d cmd/docker-trust: Remove unused command registration
Both entry points use NewRootCmd, which adds subcommands directly.
Removed the unused registry registration and constructor.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-19 13:28:28 +02:00
Paweł Gronowski 4a93a41589 cmd/docker-trust: Inline the JSON stream display helper
The plugin only needed progress display and an auxiliary callback.
Inlined that use while preserving cancellation and terminal handling.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-19 13:28:28 +02:00
Sebastiaan van Stijn e300e529d5 Merge pull request #2012 from kolyshkin/build-man
man/docker-build: fix/expand --build-arg
2026-10-19 10:43:49 +02:00
Kir Kolyshkin 72f6e50c62 man/docker-build: fix/expand --build-arg
Explain that variable value is optional and is taken from environment
if not set.

Clarify the meaning of ARG, and mention that ENV overrides ARG of the
same name.

Move example to the end, and refer to the Dockerfile and buildx docs
for more details (replacing the obsolete link).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-10-19 01:15:00 -07:00
Sebastiaan van Stijn 52a2671034 Merge pull request #7396 from docker/dependabot/github_actions/codeql-actions-073aea62d7
build(deps): bump the codeql-actions group with 3 updates
2026-10-16 16:24:33 +02:00
Sebastiaan van Stijn 1d02640576 Merge pull request #7391 from vvoland/revert-go
Revert "chore(deps): update dependency go to v1.27.1"
2026-10-16 16:23:50 +02:00
Paweł Gronowski 4d74583397 Merge pull request #7398 from thaJeztah/bump_version
bump version to 29.10.0
2026-10-16 14:46:12 +02:00
Sebastiaan van Stijn de4ddc4fae bump version to 29.10.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-10-15 21:32:57 +02:00
dependabot[bot] ccac941dd9 build(deps): bump the codeql-actions group with 3 updates
Bumps the codeql-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.38.2 to 4.38.3
- [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/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...24c54180a607b1449ed407dd24f251e4e9147c8d)

Updates `github/codeql-action/autobuild` from 4.38.2 to 4.38.3
- [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/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...24c54180a607b1449ed407dd24f251e4e9147c8d)

Updates `github/codeql-action/analyze` from 4.38.2 to 4.38.3
- [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/2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2...24c54180a607b1449ed407dd24f251e4e9147c8d)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.38.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-15 08:45:04 +00:00
Paweł Gronowski e6beb40c03 Revert "chore(deps): update dependency go to v1.27.1"
This reverts commit a3a2bb6118.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-14 21:00:31 +02:00
Alexandre Rodrigues a999520f67 opts: Reject duplicate shorthand GPU counts
`--gpus count=1,2` and `--gpus 1,2` silently replace the first count, while `--gpus 1,count=2` correctly reports a duplicate.

Normalize shorthand counts to the `count` key before checking duplicates. Tests cover both orders, multiple shorthand values, and `all`; rejected options do not append a device request.

Signed-off-by: Alexandre Rodrigues <alexandre3ylf@gmail.com>
2026-09-17 13:19:10 -03:00
279 changed files with 9256 additions and 2437 deletions
+3 -3
View File
@@ -68,7 +68,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- -
name: Build name: Build
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0 uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with: with:
targets: ${{ matrix.target }} targets: ${{ matrix.target }}
set: | set: |
@@ -99,7 +99,7 @@ jobs:
bin-image: bin-image:
if: ${{ github.event_name != 'pull_request' && github.repository == 'docker/cli' }} if: ${{ github.event_name != 'pull_request' && github.repository == 'docker/cli' }}
uses: docker/github-builder/.github/workflows/bake.yml@58cb9f5b71b1836d6f690c1e95effdeb9b98cb8a # v1.17.0 uses: docker/github-builder/.github/workflows/bake.yml@a31d2311da4d55e21b978c1c52bab82ba97d51ee # v1.19.0
permissions: permissions:
contents: read # same as global permission contents: read # same as global permission
id-token: write # for signing attestation(s) and authenticating to Docker Hub with GitHub OIDC Token id-token: write # for signing attestation(s) and authenticating to Docker Hub with GitHub OIDC Token
@@ -159,7 +159,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- -
name: Build name: Build
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0 uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with: with:
targets: plugins-cross targets: plugins-cross
set: | set: |
+4 -4
View File
@@ -64,18 +64,18 @@ jobs:
name: Update Go name: Update Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with: with:
go-version: "1.27.1" go-version: "1.27.4"
cache: false cache: false
- -
name: Initialize CodeQL name: Initialize CodeQL
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
with: with:
languages: go languages: go
- -
name: Autobuild name: Autobuild
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 uses: github/codeql-action/autobuild@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
- -
name: Perform CodeQL Analysis name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
with: with:
category: "/language:go" category: "/language:go"
+4 -1
View File
@@ -26,6 +26,9 @@ on:
jobs: jobs:
tests: tests:
permissions:
contents: read
id-token: write # needed for CodeCov; https://github.com/codecov/codecov-action/blob/v7.1.1/README.md#using-oidc
runs-on: ubuntu-26.04 runs-on: ubuntu-26.04
strategy: strategy:
fail-fast: false fail-fast: false
@@ -80,4 +83,4 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with: with:
files: ./build/coverage/coverage.txt files: ./build/coverage/coverage.txt
token: ${{ secrets.CODECOV_TOKEN }} use_oidc: true
+1 -1
View File
@@ -11,7 +11,7 @@ permissions:
jobs: jobs:
review: review:
uses: docker/docker-agent-action/.github/workflows/review-pr.yml@3654ec391b070e247de2e2e3c1ff2519b6378b3a # v2.0.9 uses: docker/docker-agent-action/.github/workflows/review-pr.yml@aaa657c53cc69ed15683cd8a985d86663a0e1594 # v2.1.0
permissions: permissions:
contents: read # Read repository files and PR diffs contents: read # Read repository files and PR diffs
pull-requests: write # Post review comments pull-requests: write # Post review comments
+12 -6
View File
@@ -26,6 +26,9 @@ on:
jobs: jobs:
ctn: ctn:
permissions:
contents: read
id-token: write # needed for CodeCov; https://github.com/codecov/codecov-action/blob/v7.1.1/README.md#using-oidc
runs-on: ubuntu-26.04 runs-on: ubuntu-26.04
steps: steps:
- -
@@ -33,7 +36,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- -
name: Test name: Test
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0 uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with: with:
targets: test-coverage targets: test-coverage
- -
@@ -41,9 +44,12 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with: with:
files: ./build/coverage/coverage.txt files: ./build/coverage/coverage.txt
token: ${{ secrets.CODECOV_TOKEN }} use_oidc: true
host: host:
permissions:
contents: read
id-token: write # needed for CodeCov; https://github.com/codecov/codecov-action/blob/v7.1.1/README.md#using-oidc
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
GOPATH: ${{ github.workspace }} GOPATH: ${{ github.workspace }}
@@ -53,9 +59,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: os:
- 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) - macos-15 # macOS 15 on arm64 (Apple Silicon M1)
- macos-26 # macOS 26 on arm64 (Apple Silicon M1)
- macos-26-intel # macOS 26 on Intel
# - 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 # - 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: steps:
- -
@@ -68,7 +74,7 @@ jobs:
name: Set up Go name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with: with:
go-version: "1.27.1" go-version: "1.27.4"
cache: false cache: false
- -
name: Test name: Test
@@ -86,4 +92,4 @@ jobs:
with: with:
files: /tmp/coverage.txt files: /tmp/coverage.txt
working-directory: ${{ env.GOPATH }}/src/github.com/docker/cli working-directory: ${{ env.GOPATH }}/src/github.com/docker/cli
token: ${{ secrets.CODECOV_TOKEN }} use_oidc: true
+2 -2
View File
@@ -38,7 +38,7 @@ jobs:
steps: steps:
- -
name: Run name: Run
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0 uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with: with:
targets: ${{ matrix.target }} targets: ${{ matrix.target }}
@@ -101,7 +101,7 @@ jobs:
name: Set up Go name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with: with:
go-version: "1.27.1" go-version: "1.27.4"
cache: false cache: false
- -
name: Run gocompat check name: Run gocompat check
+1 -11
View File
@@ -5,7 +5,7 @@ run:
# which causes it to fallback to go1.17 semantics. # 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 # TODO(thaJeztah): update "usetesting" settings to enable go1.24 features once our minimum version is go1.24
go: "1.26.9" go: "1.27.4"
timeout: 5m timeout: 5m
@@ -201,11 +201,6 @@ linters:
linters: linters:
- gosec - gosec
# TODO: make sure all packages have a description. Currently, there's 67 packages without.
- text: "package-comments: should have a package comment"
linters:
- revive
# Exclude some linters from running on tests files. # Exclude some linters from running on tests files.
- path: _test\.go - path: _test\.go
linters: linters:
@@ -227,11 +222,6 @@ linters:
linters: linters:
- staticcheck - staticcheck
# TODO(thaJeztah): remove once https://github.com/leighmcculloch/gocheckcompilerdirectives/issues/7 is fixed.
- text: "compiler directive unrecognized: //go:fix"
linters:
- gocheckcompilerdirectives
# Log a warning if an exclusion rule is unused. # Log a warning if an exclusion rule is unused.
# Default: false # Default: false
warn-unused: true warn-unused: true
+8 -6
View File
@@ -5,10 +5,12 @@ ARG BASE_VARIANT=alpine
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # 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 # 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. # that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23 ARG ALPINE_VERSION=3.24
ARG BASE_DEBIAN_DISTRO=bookworm
ARG GO_VERSION=1.26.9 # BASE_DEBIAN_DISTRO sets the version of the debian base image to use,
ARG BASE_DEBIAN_DISTRO=trixie
ARG GO_VERSION=1.27.4
# XX_VERSION specifies the version of the xx utility to use. # XX_VERSION specifies the version of the xx utility to use.
# It must be a valid tag in the docker.io/tonistiigi/xx image repository. # It must be a valid tag in the docker.io/tonistiigi/xx image repository.
@@ -25,12 +27,12 @@ ARG GOTESTSUM_VERSION=v1.13.0
# BUILDX_VERSION sets the version of buildx to use for the e2e tests. # 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 # It must be a tag in the docker.io/docker/buildx-bin image repository
# on Docker Hub. # on Docker Hub.
ARG BUILDX_VERSION=0.38.0 ARG BUILDX_VERSION=0.38.2
# COMPOSE_VERSION is the version of compose to install in the dev container. # COMPOSE_VERSION is the version of compose to install in the dev container.
# It must be a tag in the docker.io/docker/compose-bin image repository # It must be a tag in the docker.io/docker/compose-bin image repository
# on Docker Hub. # on Docker Hub.
ARG COMPOSE_VERSION=v5.6.0 ARG COMPOSE_VERSION=v5.7.0
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@@ -53,7 +55,7 @@ WORKDIR /go/src/github.com/docker/cli
FROM build-base-debian AS build-debian FROM build-base-debian AS build-debian
ARG TARGETPLATFORM ARG TARGETPLATFORM
RUN xx-apt-get install --no-install-recommends -y libc6-dev libgcc-12-dev pkgconf RUN xx-apt-get install --no-install-recommends -y libc6-dev libgcc-14-dev pkgconf
FROM build-base-${BASE_VARIANT} AS goversioninfo FROM build-base-${BASE_VARIANT} AS goversioninfo
ARG GOVERSIONINFO_VERSION ARG GOVERSIONINFO_VERSION
+1 -1
View File
@@ -1 +1 @@
29.9.1 29.10.0
+62 -2
View File
@@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"os" "os"
"sync" "sync"
"time"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/metadata" "github.com/docker/cli/cli-plugins/metadata"
@@ -32,6 +33,11 @@ import (
// called. // called.
var PersistentPreRunE func(*cobra.Command, []string) error var PersistentPreRunE func(*cobra.Command, []string) error
// finalizeHookTimeout is the timeout given for running the finalize hook.
// It contains the timeout for exporting metrics and a little bit extra in case
// shutdown does not respond to the export timeout promptly.
const finalizeHookTimeout = command.ExportTimeout + 10*time.Millisecond
// RunPlugin executes the specified plugin command // RunPlugin executes the specified plugin command
func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) error { func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) error {
tcmd := newPluginCommand(dockerCli, plugin, meta) tcmd := newPluginCommand(dockerCli, plugin, meta)
@@ -69,6 +75,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadat
stopInstrumentation(err) stopInstrumentation(err)
return err return err
} }
cobra.OnFinalize(func() { finalizeHook(dockerCli) })
}) })
return retErr return retErr
} }
@@ -83,6 +90,59 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadat
return cmd.Execute() return cmd.Execute()
} }
// finalizeHook is a hook to be run when the CLI has finished executing the run command.
// This happens after any post run methods but also always runs even when an error happens.
func finalizeHook(dockerCli *command.DockerCli) {
// Use a new context for the export so that the command being cancelled
// doesn't affect the metrics, and we get metrics for cancelled commands.
ctx, cancel := context.WithTimeout(context.Background(), command.ExportTimeout)
defer cancel()
var (
wg sync.WaitGroup
wait bool
)
if tp, ok := dockerCli.TracerProvider().(command.TracerProvider); ok {
wg.Go(func() {
if err := tp.Shutdown(ctx); err != nil {
otel.Handle(err)
}
})
wait = true
}
if mp, ok := dockerCli.MeterProvider().(command.MeterProvider); ok {
wg.Go(func() {
if err := mp.Shutdown(ctx); err != nil {
otel.Handle(err)
}
})
wait = true
}
// Wait for the wait group in another goroutine if any were created.
if !wait {
return
}
// Spawn a goroutine to wait for the wait group.
// If the shutdown does not promptly hang up with the
// cancellation of the context, we leave this goroutine
// orphaned so the process can exit.
done := make(chan struct{})
go func() {
defer close(done)
wg.Wait()
}()
select {
case <-done:
case <-time.After(finalizeHookTimeout):
// Ensure we still exit even if the shutdown doesn't work properly.
// We give 10 extra milliseconds for the cleanup to happen.
}
}
// Run is the top-level entry point to the CLI plugin framework. It should // Run is the top-level entry point to the CLI plugin framework. It should
// be called from the plugin's "main()" function. It initializes a new // be called from the plugin's "main()" function. It initializes a new
// [command.DockerCli] instance with the given options before calling // [command.DockerCli] instance with the given options before calling
@@ -212,8 +272,8 @@ func newMetadataSubcommand(plugin *cobra.Command, meta metadata.Metadata) *cobra
Use: metadata.MetadataSubcommandName, Use: metadata.MetadataSubcommandName,
Hidden: true, Hidden: true,
// Suppress the global/parent PersistentPreRunE, which // Suppress the global/parent PersistentPreRunE, which
// needlessly initializes the client and tries to // needlessly initializes the client and tries to connect to the
// connect to the daemon. // daemon.
PersistentPreRun: func(cmd *cobra.Command, args []string) {}, PersistentPreRun: func(cmd *cobra.Command, args []string) {},
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
enc := json.NewEncoder(os.Stdout) enc := json.NewEncoder(os.Stdout)
+19 -1
View File
@@ -160,7 +160,25 @@ func (tcmd *TopLevelCommand) HandleGlobalFlags() (*cobra.Command, []string, erro
return nil, nil, cmd.FlagErrorFunc()(cmd, err) return nil, nil, cmd.FlagErrorFunc()(cmd, err)
} }
return cmd, flags.Args(), nil args := flags.Args()
// A leading "--help"/"-h" is consumed above as the root's persistent
// help flag and stripped from args, so the target subcommand never sees
// it. That's fine for most subcommands, which inherit the same help
// flag instance, but "run" and "create" register their own local
// "help" flag (to avoid a shorthand clash with "-h"/"--hostname"),
// which shadows the persistent one and is left false. Propagate the
// value so "docker --help run <image>" shows help like "docker run
// --help" does, instead of running the container.
if help, _ := flags.GetBool("help"); help {
if sub, _, err := cmd.Find(args); err == nil && sub != cmd {
if sub.Flags().Lookup("help") != nil {
_ = sub.Flags().Set("help", "true")
}
}
}
return cmd, args, nil
} }
// Initialize finalises global option parsing and initializes the docker client. // Initialize finalises global option parsing and initializes the docker client.
+42
View File
@@ -108,3 +108,45 @@ func TestDecoratedName(t *testing.T) {
topLevelCommand.Annotations = map[string]string{metadata.CommandAnnotationPlugin: "true"} topLevelCommand.Annotations = map[string]string{metadata.CommandAnnotationPlugin: "true"}
assert.Equal(t, decoratedName(topLevelCommand), "pluginTopLevelCommand*") assert.Equal(t, decoratedName(topLevelCommand), "pluginTopLevelCommand*")
} }
// TestHandleGlobalFlagsHelpPropagation covers https://github.com/docker/cli/issues/7473:
// a leading "--help" is consumed as the root's persistent help flag and
// stripped from args, so a subcommand that registers its own local "help"
// flag (as "run" and "create" do, to avoid a shorthand clash with "-h") never
// sees it and runs instead of showing help.
func TestHandleGlobalFlagsHelpPropagation(t *testing.T) {
newRootCmd := func() (root, sub *cobra.Command) {
root = &cobra.Command{Use: "docker"}
root.PersistentFlags().BoolP("help", "h", false, "Print usage")
sub = &cobra.Command{Use: "run", RunE: func(cmd *cobra.Command, args []string) error { return nil }}
sub.Flags().Bool("help", false, "Print usage")
root.AddCommand(sub)
return root, sub
}
t.Run("propagates to the shadowing local help flag", func(t *testing.T) {
root, sub := newRootCmd()
tcmd := &TopLevelCommand{cmd: root, args: []string{"--help", "run", "hello-world"}}
_, args, err := tcmd.HandleGlobalFlags()
assert.NilError(t, err)
assert.DeepEqual(t, args, []string{"run", "hello-world"})
help, err := sub.Flags().GetBool("help")
assert.NilError(t, err)
assert.Equal(t, help, true)
})
t.Run("leaves the local help flag alone without --help", func(t *testing.T) {
root, sub := newRootCmd()
tcmd := &TopLevelCommand{cmd: root, args: []string{"run", "hello-world"}}
_, _, err := tcmd.HandleGlobalFlags()
assert.NilError(t, err)
help, err := sub.Flags().GetBool("help")
assert.NilError(t, err)
assert.Equal(t, help, false)
})
}
+15 -12
View File
@@ -146,24 +146,27 @@ func (c *ContainerContext) ID() string {
// slash (/) prefix stripped. Additional names for the container (related to the // slash (/) prefix stripped. Additional names for the container (related to the
// legacy `--link` feature) are omitted when formatting "truncated". // legacy `--link` feature) are omitted when formatting "truncated".
func (c *ContainerContext) Names() string { func (c *ContainerContext) Names() string {
var b strings.Builder if c.trunc {
for i, n := range c.c.Names { // When printing truncated, we only print a single name.
name := strings.TrimPrefix(n, "/") //
if c.trunc { // Pick the first name that's not a legacy link (does not have
// When printing truncated, we only print a single name. // slashes inside the name itself (e.g., "/other-container/link")).
// // Normally this would be the first name found.
// Pick the first name that's not a legacy link (does not have for _, n := range c.c.Names {
// slashes inside the name itself (e.g., "/other-container/link")). if name := strings.TrimPrefix(n, "/"); strings.IndexByte(name, '/') == -1 {
// Normally this would be the first name found.
if strings.IndexByte(name, '/') == -1 {
return name return name
} }
continue
} }
// No name without slashes was found; this can happen when connected
// to a classic Swarm API, which prefixes names with the node-name
// ("/<node-name>/<container-name>"). Fall back to printing all names.
}
var b strings.Builder
for i, n := range c.c.Names {
if i > 0 { if i > 0 {
b.WriteByte(',') b.WriteByte(',')
} }
b.WriteString(name) b.WriteString(strings.TrimPrefix(n, "/"))
} }
return b.String() return b.String()
} }
+20
View File
@@ -48,6 +48,25 @@ func TestContainerPsContext(t *testing.T) {
expValue: "foobar_baz", expValue: "foobar_baz",
call: ctx.Names, call: ctx.Names,
}, },
{
container: container.Summary{Names: []string{"/other/link", "/foobar_baz"}},
trunc: true,
expValue: "foobar_baz",
call: ctx.Names,
},
{
container: container.Summary{Names: []string{"/foobar_baz", "/other/link"}},
expValue: "foobar_baz,other/link",
call: ctx.Names,
},
{
// Names returned by a classic Swarm API are prefixed with the
// node-name; see https://github.com/docker/cli/pull/6875
container: container.Summary{Names: []string{"/node-1/foobar_baz"}},
trunc: true,
expValue: "node-1/foobar_baz",
call: ctx.Names,
},
{ {
container: container.Summary{Image: "ubuntu"}, container: container.Summary{Image: "ubuntu"},
trunc: true, trunc: true,
@@ -257,6 +276,7 @@ func TestContainerPsContext(t *testing.T) {
} }
} }
//nolint:dupword // ignore duplicate "ubuntu" in test fixtures
func TestContainerContextWrite(t *testing.T) { func TestContainerContextWrite(t *testing.T) {
unixTime := time.Now().AddDate(0, 0, -1).Unix() unixTime := time.Now().AddDate(0, 0, -1).Unix()
expectedTime := time.Unix(unixTime, 0).String() expectedTime := time.Unix(unixTime, 0).String()
+30 -2
View File
@@ -10,8 +10,10 @@ import (
"slices" "slices"
"github.com/containerd/errdefs" "github.com/containerd/errdefs"
"github.com/containerd/platforms"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/manifest/store" "github.com/docker/cli/cli/manifest/store"
"github.com/docker/cli/internal/registryclient" "github.com/docker/cli/internal/registryclient"
@@ -20,6 +22,23 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var (
// similar to https://github.com/containerd/platforms/blob/v1.0.0-rc.5/database.go#L29-L38
knownOSes = []string{
"aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos",
"ios", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris",
"windows", "zos",
}
// similar to https://github.com/containerd/platforms/blob/v1.0.0-rc.5/database.go#L51-L60
knownArches = []string{
"386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64",
"ppc64le", "loong64", "mips", "mipsle", "mips64", "mips64le", "mips64p32",
"mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc",
"sparc64", "wasm",
}
)
type annotateOptions struct { type annotateOptions struct {
target string // the target manifest list name (also transaction ID) target string // the target manifest list name (also transaction ID)
image string // the manifest to annotate within the list image string // the manifest to annotate within the list
@@ -97,6 +116,8 @@ func newAnnotateCommand(dockerCLI command.Cli) *cobra.Command {
flags.StringSliceVar(&opts.osFeatures, "os-features", []string{}, "Set operating system feature") flags.StringSliceVar(&opts.osFeatures, "os-features", []string{}, "Set operating system feature")
flags.StringVar(&opts.variant, "variant", "", "Set architecture variant") flags.StringVar(&opts.variant, "variant", "", "Set architecture variant")
_ = cmd.RegisterFlagCompletionFunc("os", completion.FromList(knownOSes...))
_ = cmd.RegisterFlagCompletionFunc("arch", completion.FromList(knownArches...))
return cmd return cmd
} }
@@ -139,8 +160,15 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error {
imageManifest.Descriptor.Platform.OSVersion = opts.osVersion imageManifest.Descriptor.Platform.OSVersion = opts.osVersion
} }
if !isValidOSArch(imageManifest.Descriptor.Platform.OS, imageManifest.Descriptor.Platform.Architecture) { // Validate platform syntax, without restricting OS/architecture combinations.
return fmt.Errorf("manifest entry for image has unsupported os/arch combination: %s/%s", opts.os, opts.arch) //
// TODO(thaJeztah): Implement a platforms.Validate in containerd/platforms and replace this code.
p := imageManifest.Descriptor.Platform
if p.OS == "" || p.Architecture == "" {
return fmt.Errorf("manifest entry for image has missing os/architecture: %q/%q", p.OS, p.Architecture)
}
if _, err := platforms.Parse(platforms.FormatAll(*p)); err != nil {
return fmt.Errorf("manifest entry for image has invalid platform: %w", err)
} }
return manifestStore.Save(targetRef, imgRef, imageManifest) return manifestStore.Save(targetRef, imgRef, imageManifest)
} }
+8 -7
View File
@@ -58,15 +58,16 @@ func TestManifestAnnotate(t *testing.T) {
assert.ErrorContains(t, cmd.Execute(), expectedError) assert.ErrorContains(t, cmd.Execute(), expectedError)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"}) cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.Flags().Set("os", "freebsd") assert.NilError(t, cmd.Flags().Set("os", "freebsd"))
cmd.Flags().Set("arch", "fake") assert.NilError(t, cmd.Flags().Set("arch", "<invalid>"))
cmd.Flags().Set("os-version", "1") assert.NilError(t, cmd.Flags().Set("os-version", "1"))
cmd.Flags().Set("os-features", "feature1") assert.NilError(t, cmd.Flags().Set("os-features", "feature1"))
cmd.Flags().Set("variant", "v7") assert.NilError(t, cmd.Flags().Set("variant", "v7"))
expectedError = "manifest entry for image has unsupported os/arch combination"
expectedError = "manifest entry for image has invalid platform"
assert.ErrorContains(t, cmd.Execute(), expectedError) assert.ErrorContains(t, cmd.Execute(), expectedError)
cmd.Flags().Set("arch", "arm") assert.NilError(t, cmd.Flags().Set("arch", "arm"))
assert.NilError(t, cmd.Execute()) assert.NilError(t, cmd.Execute())
cmd = newInspectCommand(cli) cmd = newInspectCommand(cli)
-47
View File
@@ -9,53 +9,6 @@ import (
"github.com/docker/cli/cli/manifest/types" "github.com/docker/cli/cli/manifest/types"
) )
type osArch struct {
os string
arch string
}
// Remove any unsupported os/arch combo
// list of valid os/arch values (see "Optional Environment Variables" section
// of https://go.dev/doc/install/source
// Added linux/s390x as we know System z support already exists
// Keep in sync with _docker_manifest_annotate in contrib/completion/bash/docker
var validOSArches = map[osArch]bool{
{os: "darwin", arch: "386"}: true,
{os: "darwin", arch: "amd64"}: true,
{os: "darwin", arch: "arm"}: true,
{os: "darwin", arch: "arm64"}: true,
{os: "dragonfly", arch: "amd64"}: true,
{os: "freebsd", arch: "386"}: true,
{os: "freebsd", arch: "amd64"}: true,
{os: "freebsd", arch: "arm"}: true,
{os: "linux", arch: "386"}: true,
{os: "linux", arch: "amd64"}: true,
{os: "linux", arch: "arm"}: true,
{os: "linux", arch: "arm64"}: true,
{os: "linux", arch: "ppc64le"}: true,
{os: "linux", arch: "mips64"}: true,
{os: "linux", arch: "mips64le"}: true,
{os: "linux", arch: "riscv64"}: true,
{os: "linux", arch: "s390x"}: true,
{os: "netbsd", arch: "386"}: true,
{os: "netbsd", arch: "amd64"}: true,
{os: "netbsd", arch: "arm"}: true,
{os: "openbsd", arch: "386"}: true,
{os: "openbsd", arch: "amd64"}: true,
{os: "openbsd", arch: "arm"}: true,
{os: "plan9", arch: "386"}: true,
{os: "plan9", arch: "amd64"}: true,
{os: "solaris", arch: "amd64"}: true,
{os: "windows", arch: "386"}: true,
{os: "windows", arch: "amd64"}: true,
}
func isValidOSArch(os string, arch string) bool {
// check for existence of this combo
_, ok := validOSArches[osArch{os, arch}]
return ok
}
func normalizeReference(ref string) (reference.Named, error) { func normalizeReference(ref string) (reference.Named, error) {
namedRef, err := reference.ParseNormalizedNamed(ref) namedRef, err := reference.ParseNormalizedNamed(ref)
if err != nil { if err != nil {
+6 -6
View File
@@ -19,6 +19,7 @@ import (
"github.com/docker/cli/internal/tui" "github.com/docker/cli/internal/tui"
registrytypes "github.com/moby/moby/api/types/registry" registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client" "github.com/moby/moby/client"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@@ -226,7 +227,7 @@ func loginWithStoredCredentials(ctx context.Context, dockerCLI command.Cli, auth
return resp.Auth.Status, err return resp.Auth.Status, err
} }
func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (msg string, _ error) { func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (message string, _ error) {
// Some links documenting this: // Some links documenting this:
// - https://code.google.com/archive/p/mintty/issues/56 // - https://code.google.com/archive/p/mintty/issues/56
// - https://github.com/docker/docker/issues/15272 // - https://github.com/docker/docker/issues/15272
@@ -240,13 +241,12 @@ func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, de
// If we're logging into the index server and the user didn't provide a username or password, use the device flow // If we're logging into the index server and the user didn't provide a username or password, use the device flow
if serverAddress == registry.IndexServer && opts.user == "" && opts.password == "" { if serverAddress == registry.IndexServer && opts.user == "" && opts.password == "" {
var err error msg, err := loginWithDeviceCodeFlow(ctx, dockerCLI)
msg, err = loginWithDeviceCodeFlow(ctx, dockerCLI) if err == nil || !errors.Is(err, manager.ErrDeviceLoginStartFail) {
// if the error represents a failure to initiate the device-code flow,
// then we fallback to regular cli credentials login
if !errors.Is(err, manager.ErrDeviceLoginStartFail) {
return msg, err return msg, err
} }
logrus.WithError(err).Debug("failed to start web-based login")
_, _ = fmt.Fprint(dockerCLI.Err(), "Failed to start web-based login - falling back to command line login...\n\n") _, _ = fmt.Fprint(dockerCLI.Err(), "Failed to start web-based login - falling back to command line login...\n\n")
} }
+2 -2
View File
@@ -210,9 +210,9 @@ func TestResourceOptionsToResourceRequirementsSwap(t *testing.T) {
r, err = swapOptions.ToResourceRequirements(flags) r, err = swapOptions.ToResourceRequirements(flags)
assert.NilError(t, err) assert.NilError(t, err)
assert.Check(t, r.SwapBytes != nil) assert.Check(t, r.SwapBytes != nil)
assert.Check(t, is.Equal(*(r.SwapBytes), int64(86000))) assert.Check(t, is.Equal(*r.SwapBytes, int64(86000)))
assert.Check(t, r.MemorySwappiness != nil) assert.Check(t, r.MemorySwappiness != nil)
assert.Check(t, is.Equal(*(r.MemorySwappiness), int64(23))) assert.Check(t, is.Equal(*r.MemorySwappiness, int64(23)))
} }
func TestToServiceNetwork(t *testing.T) { func TestToServiceNetwork(t *testing.T) {
+2 -2
View File
@@ -20,7 +20,7 @@ import (
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
) )
const exportTimeout = 50 * time.Millisecond const ExportTimeout = 50 * time.Millisecond
// TracerProvider is an extension of the trace.TracerProvider interface for CLI programs. // TracerProvider is an extension of the trace.TracerProvider interface for CLI programs.
type TracerProvider interface { type TracerProvider interface {
@@ -205,7 +205,7 @@ func (r *cliReader) Shutdown(ctx context.Context) error {
// We don't want CLI metrics to prevent the CLI from exiting // We don't want CLI metrics to prevent the CLI from exiting
// so if there's some kind of issue we need to abort pretty // so if there's some kind of issue we need to abort pretty
// quickly. // quickly.
ctx, cancel := context.WithTimeout(ctx, exportTimeout) ctx, cancel := context.WithTimeout(ctx, ExportTimeout)
defer cancel() defer cancel()
return r.ForceFlush(ctx) return r.ForceFlush(ctx)
+6 -1
View File
@@ -99,6 +99,10 @@ func dockerSpanExporter(ctx context.Context, cli Cli) []sdktrace.TracerProviderO
opts := []otlptracegrpc.Option{ opts := []otlptracegrpc.Option{
otlptracegrpc.WithEndpoint(endpoint), otlptracegrpc.WithEndpoint(endpoint),
// The whole export is bounded by ExportTimeout, which is too short for a retry
// backoff to complete. With retries on, a refused connection (for example a stale
// Docker Desktop socket) waits out the full timeout instead of failing right away.
otlptracegrpc.WithRetry(otlptracegrpc.RetryConfig{Enabled: false}),
} }
if !secure { if !secure {
opts = append(opts, otlptracegrpc.WithInsecure()) opts = append(opts, otlptracegrpc.WithInsecure())
@@ -109,7 +113,7 @@ func dockerSpanExporter(ctx context.Context, cli Cli) []sdktrace.TracerProviderO
otel.Handle(err) otel.Handle(err)
return nil return nil
} }
return []sdktrace.TracerProviderOption{sdktrace.WithBatcher(exp, sdktrace.WithExportTimeout(exportTimeout))} return []sdktrace.TracerProviderOption{sdktrace.WithBatcher(exp, sdktrace.WithExportTimeout(ExportTimeout))}
} }
func dockerMetricExporter(ctx context.Context, cli Cli) []sdkmetric.Option { func dockerMetricExporter(ctx context.Context, cli Cli) []sdkmetric.Option {
@@ -120,6 +124,7 @@ func dockerMetricExporter(ctx context.Context, cli Cli) []sdkmetric.Option {
opts := []otlpmetricgrpc.Option{ opts := []otlpmetricgrpc.Option{
otlpmetricgrpc.WithEndpoint(endpoint), otlpmetricgrpc.WithEndpoint(endpoint),
otlpmetricgrpc.WithRetry(otlpmetricgrpc.RetryConfig{Enabled: false}),
} }
if !secure { if !secure {
opts = append(opts, otlpmetricgrpc.WithInsecure()) opts = append(opts, otlpmetricgrpc.WithInsecure())
+1 -1
View File
@@ -85,7 +85,7 @@ func startCobraCommandTimer(mp metric.MeterProvider, attrs []attribute.KeyValue)
return func(err error) { return func(err error) {
// Use a new context for the export so that the command being cancelled // Use a new context for the export so that the command being cancelled
// doesn't affect the metrics, and we get metrics for cancelled commands. // doesn't affect the metrics, and we get metrics for cancelled commands.
ctx, cancel := context.WithTimeout(context.Background(), exportTimeout) ctx, cancel := context.WithTimeout(context.Background(), ExportTimeout)
defer cancel() defer cancel()
duration := float64(time.Since(start)) / float64(time.Millisecond) duration := float64(time.Since(start)) / float64(time.Millisecond)
-4
View File
@@ -255,7 +255,6 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
return nil return nil
} }
//nolint:unparam
func mergeUlimitsConfig(dst, src reflect.Value) error { func mergeUlimitsConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().Set(src.Elem()) dst.Elem().Set(src.Elem())
@@ -263,7 +262,6 @@ func mergeUlimitsConfig(dst, src reflect.Value) error {
return nil return nil
} }
//nolint:unparam
func mergeShellCommand(dst, src reflect.Value) error { func mergeShellCommand(dst, src reflect.Value) error {
if src.Len() != 0 { if src.Len() != 0 {
dst.Set(src) dst.Set(src)
@@ -271,7 +269,6 @@ func mergeShellCommand(dst, src reflect.Value) error {
return nil return nil
} }
//nolint:unparam
func mergeServiceNetworkConfig(dst, src reflect.Value) error { func mergeServiceNetworkConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases")) dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases"))
@@ -285,7 +282,6 @@ func mergeServiceNetworkConfig(dst, src reflect.Value) error {
return nil return nil
} }
//nolint:unparam
func mergeUint64(dst, src reflect.Value) error { func mergeUint64(dst, src reflect.Value) error {
if !src.IsNil() { if !src.IsNil() {
dst.Elem().Set(src.Elem()) dst.Elem().Set(src.Elem())
+6 -3
View File
@@ -27,8 +27,13 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
})) }))
cli.SetOut(outStream) cli.SetOut(outStream)
r, _, err := os.Pipe() r, w, err := os.Pipe()
assert.NilError(t, err) assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r)) cli.SetIn(streams.NewIn(r))
notifyCtx, notifyCancel := context.WithCancel(ctx) notifyCtx, notifyCancel := context.WithCancel(ctx)
@@ -58,8 +63,6 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
}() }()
} }
assert.Check(t, cli.OutBuffer().Len() > 0)
// a small delay to ensure the plugin is prompting // a small delay to ensure the plugin is prompting
time.Sleep(100 * time.Microsecond) time.Sleep(100 * time.Microsecond)
+36 -4
View File
@@ -11,8 +11,9 @@ import (
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/docker/cli/cli/streams" "github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/jsonstream" "github.com/moby/moby/api/types/jsonstream"
registrytypes "github.com/moby/moby/api/types/registry" registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client/pkg/jsonmessage"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/theupdateframework/notary/client" "github.com/theupdateframework/notary/client"
"github.com/theupdateframework/notary/tuf/data" "github.com/theupdateframework/notary/tuf/data"
@@ -46,7 +47,7 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
// Count the times of calling for handleTarget, // Count the times of calling for handleTarget,
// if it is called more that once, that should be considered an error in a trusted push. // if it is called more that once, that should be considered an error in a trusted push.
cnt := 0 cnt := 0
handleTarget := func(msg jsonstream.JSONMessage) { handleTarget := func(msg jsonstream.Message) {
cnt++ cnt++
if cnt > 1 { if cnt > 1 {
// handleTarget should only be called once. This will be treated as an error. // handleTarget should only be called once. This will be treated as an error.
@@ -78,14 +79,14 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
default: default:
// We want trust signatures to always take an explicit tag, // We want trust signatures to always take an explicit tag,
// otherwise it will act as an untrusted push. // otherwise it will act as an untrusted push.
if err := jsonstream.Display(ctx, in, ioStreams.Out()); err != nil { if err := displayJSONMessages(ctx, in, ioStreams.Out(), nil); err != nil {
return err return err
} }
_, _ = fmt.Fprintln(ioStreams.Err(), "No tag specified, skipping trust metadata push") _, _ = fmt.Fprintln(ioStreams.Err(), "No tag specified, skipping trust metadata push")
return nil return nil
} }
if err := jsonstream.Display(ctx, in, ioStreams.Out(), jsonstream.WithAuxCallback(handleTarget)); err != nil { if err := displayJSONMessages(ctx, in, ioStreams.Out(), handleTarget); err != nil {
return err return err
} }
@@ -147,3 +148,34 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
_, _ = fmt.Fprintf(ioStreams.Out(), "Successfully signed %s:%s\n", repoInfo.Name.Name(), tag) _, _ = fmt.Fprintf(ioStreams.Out(), "Successfully signed %s:%s\n", repoInfo.Name.Name(), tag)
return nil return nil
} }
type ctxReader struct {
err chan error
r io.Reader
}
func (r *ctxReader) Read(p []byte) (int, error) {
select {
case err := <-r.err:
return 0, err
default:
return r.r.Read(p)
}
}
// displayJSONMessages prints the JSON messages from in to out. It returns
// ctx.Err() if ctx is canceled, but not when in is closed.
func displayJSONMessages(ctx context.Context, in io.Reader, out *streams.Out, auxCallback func(jsonstream.Message)) error {
if ctx.Err() != nil {
return ctx.Err()
}
reader := &ctxReader{err: make(chan error, 1), r: in}
stop := context.AfterFunc(ctx, func() { reader.err <- ctx.Err() })
defer stop()
if err := jsonmessage.DisplayJSONMessagesStream(reader, out, out.FD(), out.IsTerminal(), auxCallback); err != nil {
return err
}
return ctx.Err()
}
-32
View File
@@ -1,32 +0,0 @@
package trust
import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/commands"
"github.com/spf13/cobra"
)
func init() {
commands.Register(newTrustCommand)
}
// newTrustCommand returns a cobra command for `trust` subcommands.
func newTrustCommand(dockerCLI command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "trust",
Short: "Manage trust on Docker images",
Args: cli.NoArgs,
RunE: command.ShowHelp(dockerCLI.Err()),
DisableFlagsInUseLine: true,
}
cmd.AddCommand(
newRevokeCommand(dockerCLI),
newSignCommand(dockerCLI),
newTrustKeyCommand(dockerCLI),
newTrustSignerCommand(dockerCLI),
newInspectCommand(dockerCLI),
)
return cmd
}
+2 -2
View File
@@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cmd/docker-trust/internal/trust" "github.com/docker/cli/cmd/docker-trust/internal/trust"
"github.com/docker/cli/internal/lazyregexp"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/theupdateframework/notary" "github.com/theupdateframework/notary"
"github.com/theupdateframework/notary/trustmanager" "github.com/theupdateframework/notary/trustmanager"
@@ -41,7 +41,7 @@ func newKeyGenerateCommand(dockerCLI command.Streams) *cobra.Command {
} }
// key names can use lowercase alphanumeric + _ + - characters // key names can use lowercase alphanumeric + _ + - characters
var validKeyName = lazyregexp.New(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString var validKeyName = regexp.MustCompile(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
// validate that all of the key names are unique and are alphanumeric + _ + - // validate that all of the key names are unique and are alphanumeric + _ + -
// and that we do not already have public key files in the target dir on disk // and that we do not already have public key files in the target dir on disk
+2 -2
View File
@@ -7,12 +7,12 @@ import (
"io" "io"
"os" "os"
"path" "path"
"regexp"
"strings" "strings"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cmd/docker-trust/internal/trust" "github.com/docker/cli/cmd/docker-trust/internal/trust"
"github.com/docker/cli/internal/lazyregexp"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/theupdateframework/notary/client" "github.com/theupdateframework/notary/client"
@@ -45,7 +45,7 @@ func newSignerAddCommand(dockerCLI command.Cli) *cobra.Command {
return cmd return cmd
} }
var validSignerName = lazyregexp.New(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString var validSignerName = regexp.MustCompile(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
func addSigner(ctx context.Context, dockerCLI command.Cli, options signerAddOptions) error { func addSigner(ctx context.Context, dockerCLI command.Cli, options signerAddOptions) error {
signerName := options.signer signerName := options.signer
+9
View File
@@ -580,6 +580,15 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error {
} }
// Other missing or invalid plugins fall through to cmd.ExecuteContext(), // Other missing or invalid plugins fall through to cmd.ExecuteContext(),
// which reports the standard unknown-command error. // which reports the standard unknown-command error.
//
// Cobra handles "--version" before it checks for unknown commands,
// so unset it to make "docker nonexistent --version" fail instead
// of printing the version. A global "--version" flag (as in
// "docker --version nonexistent") was already parsed, and still
// prints the version.
if !cmd.Flags().Changed("version") {
cmd.Version = ""
}
} }
} }
+1
View File
@@ -4156,6 +4156,7 @@ _docker_manifest_annotate() {
amd64 amd64
arm arm
arm64 arm64
loong64
mips64 mips64
mips64le mips64le
ppc64le ppc64le
+1 -1
View File
@@ -2,7 +2,7 @@
# ALPINE_VERSION sets the version of the alpine base image to use. # ALPINE_VERSION sets the version of the alpine base image to use.
# It must be a supported tag in the docker.io/library/alpine image repository. # It must be a supported tag in the docker.io/library/alpine image repository.
ARG ALPINE_VERSION=3.23 ARG ALPINE_VERSION=3.24
FROM alpine:${ALPINE_VERSION} AS gen FROM alpine:${ALPINE_VERSION} AS gen
RUN apk add --no-cache bash git RUN apk add --no-cache bash git
+3 -3
View File
@@ -1,16 +1,16 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.9 ARG GO_VERSION=1.27.4
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # 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 # 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. # that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23 ARG ALPINE_VERSION=3.24
# BUILDX_VERSION sets the version of buildx to install in the dev container. # BUILDX_VERSION sets the version of buildx to install in the dev container.
# It must be a valid tag in the docker.io/docker/buildx-bin image repository # It must be a valid tag in the docker.io/docker/buildx-bin image repository
# on Docker Hub. # on Docker Hub.
ARG BUILDX_VERSION=0.38.0 ARG BUILDX_VERSION=0.38.2
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang
+3 -3
View File
@@ -1,13 +1,13 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.9 ARG GO_VERSION=1.27.4
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # 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 # 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. # that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23 ARG ALPINE_VERSION=3.24
# GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use. # GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use.
ARG GOLANGCI_LINT_VERSION=v2.10.1 ARG GOLANGCI_LINT_VERSION=v2.14.0
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
+3 -3
View File
@@ -1,12 +1,12 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.9 ARG GO_VERSION=1.27.4
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image. # 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 # 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. # that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23 ARG ALPINE_VERSION=3.24
ARG MODOUTDATED_VERSION=v0.8.0 ARG MODOUTDATED_VERSION=v0.9.0
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
ENV GOTOOLCHAIN=local ENV GOTOOLCHAIN=local
@@ -44,8 +44,8 @@ created. Supported `Dockerfile` instructions:
$ docker ps $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:24.04 /bin/bash 7 days ago Up 25 hours focused_hamilton 197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
$ docker commit c3f279d17e0a svendowideit/testimage:version3 $ docker commit c3f279d17e0a svendowideit/testimage:version3
@@ -63,8 +63,8 @@ svendowideit/testimage version3 f5283438590d 16 sec
$ docker ps $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:24.04 /bin/bash 7 days ago Up 25 hours focused_hamilton 197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
$ docker inspect -f "{{ .Config.Env }}" c3f279d17e0a $ docker inspect -f "{{ .Config.Env }}" c3f279d17e0a
@@ -85,8 +85,8 @@ $ docker inspect -f "{{ .Config.Env }}" f5283438590d
$ docker ps $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:24.04 /bin/bash 7 days ago Up 25 hours focused_hamilton 197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
$ docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" c3f279d17e0a svendowideit/testimage:version4 $ docker commit --change='CMD ["apachectl", "-DFOREGROUND"]' -c "EXPOSE 80" c3f279d17e0a svendowideit/testimage:version4
@@ -100,6 +100,6 @@ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89373736e2e7 testimage:version4 "apachectl -DFOREGROU" 3 seconds ago Up 2 seconds 80/tcp distracted_fermat 89373736e2e7 testimage:version4 "apachectl -DFOREGROU" 3 seconds ago Up 2 seconds 80/tcp distracted_fermat
c3f279d17e0a ubuntu:24.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:24.04 /bin/bash 7 days ago Up 25 hours focused_hamilton 197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
``` ```
+5 -5
View File
@@ -33,7 +33,7 @@ Running `docker ps --no-trunc` showing 2 linked containers.
$ docker ps --no-trunc $ docker ps --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca5534a51dd04bbcebe9b23ba05f389466cf0c190f1f8f182d7eea92a9671d00 ubuntu:24.04 bash 17 seconds ago Up 16 seconds 3300-3310/tcp webapp ca5534a51dd04bbcebe9b23ba05f389466cf0c190f1f8f182d7eea92a9671d00 ubuntu:26.04 bash 17 seconds ago Up 16 seconds 3300-3310/tcp webapp
9ca9747b233100676a48cc7806131586213fa5dab86dd1972d6a8732e3a84a4d crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db 9ca9747b233100676a48cc7806131586213fa5dab86dd1972d6a8732e3a84a4d crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
``` ```
@@ -240,13 +240,13 @@ CONTAINER ID IMAGE COMMAND CREATED
919e1179bdb8 ubuntu-c1 "top" About a minute ago Up About a minute admiring_lovelace 919e1179bdb8 ubuntu-c1 "top" About a minute ago Up About a minute admiring_lovelace
``` ```
Match containers based on the `ubuntu` version `24.04` image: Match containers based on the `ubuntu` version `26.04` image:
```console ```console
$ docker ps --filter ancestor=ubuntu:24.04 $ docker ps --filter ancestor=ubuntu:26.04
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
82a598284012 ubuntu:24.04 "top" 3 minutes ago Up 3 minutes sleepy_bose 82a598284012 ubuntu:26.04 "top" 3 minutes ago Up 3 minutes sleepy_bose
``` ```
The following matches containers based on the layer `d0e008c6cf02` or an image The following matches containers based on the layer `d0e008c6cf02` or an image
@@ -256,7 +256,7 @@ that have this layer in its layer stack.
$ docker ps --filter ancestor=d0e008c6cf02 $ docker ps --filter ancestor=d0e008c6cf02
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
82a598284012 ubuntu:24.04 "top" 3 minutes ago Up 3 minutes sleepy_bose 82a598284012 ubuntu:26.04 "top" 3 minutes ago Up 3 minutes sleepy_bose
``` ```
#### Create time #### Create time
+19 -19
View File
@@ -66,18 +66,18 @@ docker.io/library/debian:latest
Docker images can consist of multiple layers. In the example above, the image Docker images can consist of multiple layers. In the example above, the image
consists of a single layer; `e756f3fdd6a3`. consists of a single layer; `e756f3fdd6a3`.
Layers can be reused by images. For example, the `debian:bookworm` image shares Layers can be reused by images. For example, the `debian:trixie` image shares
its layer with the `debian:latest`. Pulling the `debian:bookworm` image therefore its layer with the `debian:latest`. Pulling the `debian:trixie` image therefore
only pulls its metadata, but not its layers, because the layer is already present only pulls its metadata, but not its layers, because the layer is already present
locally: locally:
```console ```console
$ docker image pull debian:bookworm $ docker image pull debian:trixie
bookworm: Pulling from library/debian trixie: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510 Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:bookworm Status: Downloaded newer image for debian:trixie
docker.io/library/debian:bookworm docker.io/library/debian:trixie
``` ```
To see which images are present locally, use the [`docker images`](image_ls.md) To see which images are present locally, use the [`docker images`](image_ls.md)
@@ -87,13 +87,13 @@ command:
$ docker images $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
debian bookworm 4eacea30377a 8 days ago 124MB debian trixie 4eacea30377a 8 days ago 124MB
debian latest 4eacea30377a 8 days ago 124MB debian latest 4eacea30377a 8 days ago 124MB
``` ```
Docker uses a content-addressable image store, and the image ID is a SHA256 Docker uses a content-addressable image store, and the image ID is a SHA256
digest covering the image's configuration and layers. In the example above, digest covering the image's configuration and layers. In the example above,
`debian:bookworm` and `debian:latest` have the same image ID because they are `debian:trixie` and `debian:latest` have the same image ID because they are
the same image tagged with different names. Because they are the same image, the same image tagged with different names. Because they are the same image,
their layers are stored only once and do not consume extra disk space. their layers are stored only once and do not consume extra disk space.
@@ -106,8 +106,8 @@ refer to [understand images, containers, and storage drivers](https://docs.docke
So far, you've pulled images by their name (and "tag"). Using names and tags is So far, you've pulled images by their name (and "tag"). Using names and tags is
a convenient way to work with images. When using tags, you can `docker pull` an a convenient way to work with images. When using tags, you can `docker pull` an
image again to make sure you have the most up-to-date version of that image. image again to make sure you have the most up-to-date version of that image.
For example, `docker pull ubuntu:24.04` pulls the latest version of the Ubuntu For example, `docker pull ubuntu:26.04` pulls the latest version of the Ubuntu
24.04 image. 26.04 image.
In some cases you don't want images to be updated to newer versions, but prefer In some cases you don't want images to be updated to newer versions, but prefer
to use a fixed version of an image. Docker enables you to pull an image by its to use a fixed version of an image. Docker enables you to pull an image by its
@@ -116,16 +116,16 @@ of an image to pull. Doing so, allows you to "pin" an image to that version,
and guarantee that the image you're using is always the same. and guarantee that the image you're using is always the same.
To know the digest of an image, pull the image first. Let's pull the latest To know the digest of an image, pull the image first. Let's pull the latest
`ubuntu:24.04` image from Docker Hub: `ubuntu:26.04` image from Docker Hub:
```console ```console
$ docker pull ubuntu:24.04 $ docker pull ubuntu:26.04
24.04: Pulling from library/ubuntu 26.04: Pulling from library/ubuntu
125a6e411906: Pull complete 125a6e411906: Pull complete
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30 Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:24.04 Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:24.04 docker.io/library/ubuntu:26.04
``` ```
Docker prints the digest of the image after the pull has finished. In the example Docker prints the digest of the image after the pull has finished. In the example
@@ -213,11 +213,11 @@ shorthand) to see the images that were pulled. The example below shows all the
```console ```console
$ docker image ls --filter reference=ubuntu $ docker image ls --filter reference=ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 8a3cdc4d1ad3 3 weeks ago 77.9MB ubuntu 24.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu jammy 8a3cdc4d1ad3 3 weeks ago 77.9MB ubuntu noble 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 24.04 35a88802559d 6 weeks ago 78.1MB ubuntu 26.04 35a88802559d 6 weeks ago 78.1MB
ubuntu latest 35a88802559d 6 weeks ago 78.1MB ubuntu latest 35a88802559d 6 weeks ago 78.1MB
ubuntu noble 35a88802559d 6 weeks ago 78.1MB ubuntu resolute 35a88802559d 6 weeks ago 78.1MB
``` ```
### Cancel a pull ### Cancel a pull
+3 -4
View File
@@ -180,13 +180,12 @@ code, and authenticate.
```console ```console
$ docker login $ docker login
USING WEB-BASED LOGIN Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: LNFR-PGCJ Your one-time device confirmation code is: LNFR-PGCJ
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate Open this URL to authenticate: https://login.docker.com/activate?user_code=LNFR-PGCJ
Waiting for authentication in the browser… Press ENTER to open the URL in your browser, or Ctrl+C to cancel.
``` ```
After entering the code in your browser, you are authenticated to Docker Hub After entering the code in your browser, you are authenticated to Docker Hub
+1 -1
View File
@@ -706,7 +706,7 @@ follows:
| `node.platform.os` | Node operating system | `node.platform.os==windows` | | `node.platform.os` | Node operating system | `node.platform.os==windows` |
| `node.platform.arch` | Node architecture | `node.platform.arch==x86_64` | | `node.platform.arch` | Node architecture | `node.platform.arch==x86_64` |
| `node.labels` | User-defined node labels | `node.labels.security==high` | | `node.labels` | User-defined node labels | `node.labels.security==high` |
| `engine.labels` | Docker Engine's labels | `engine.labels.operatingsystem==ubuntu-24.04` | | `engine.labels` | Docker Engine's labels | `engine.labels.operatingsystem==ubuntu-26.04` |
`engine.labels` apply to Docker Engine labels like operating system, drivers, `engine.labels` apply to Docker Engine labels like operating system, drivers,
etc. Swarm administrators add `node.labels` for operational purposes by using etc. Swarm administrators add `node.labels` for operational purposes by using
+2 -2
View File
@@ -339,8 +339,8 @@ $ docker events --filter 'type=network'
$ docker events --filter 'container=container_1' --filter 'container=container_2' $ docker events --filter 'container=container_1' --filter 'container=container_2'
2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04) 2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (imager=redis:7.2) 2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (imager=redis:7.2)
2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2) 2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2)
+19 -19
View File
@@ -35,7 +35,7 @@ reference to create or run a container based on an image.
An image tag is the image version, which defaults to `latest` when omitted. Use An image tag is the image version, which defaults to `latest` when omitted. Use
the tag to run a container from specific version of an image. For example, to the tag to run a container from specific version of an image. For example, to
run version `24.04` of the `ubuntu` image: `docker run ubuntu:24.04`. run version `26.04` of the `ubuntu` image: `docker run ubuntu:26.04`.
#### Image digests #### Image digests
@@ -406,14 +406,14 @@ We have four ways to set user memory usage:
Examples: Examples:
```console ```console
$ docker run -it ubuntu:24.04 /bin/bash $ docker run -it ubuntu:26.04 /bin/bash
``` ```
We set nothing about memory, this means the processes in the container can use We set nothing about memory, this means the processes in the container can use
as much memory and swap memory as they need. as much memory and swap memory as they need.
```console ```console
$ docker run -it -m 300M --memory-swap -1 ubuntu:24.04 /bin/bash $ docker run -it -m 300M --memory-swap -1 ubuntu:26.04 /bin/bash
``` ```
We set memory limit and disabled swap memory limit, this means the processes in We set memory limit and disabled swap memory limit, this means the processes in
@@ -421,7 +421,7 @@ the container can use 300M memory and as much swap memory as they need (if the
host supports swap memory). host supports swap memory).
```console ```console
$ docker run -it -m 300M ubuntu:24.04 /bin/bash $ docker run -it -m 300M ubuntu:26.04 /bin/bash
``` ```
We set memory limit only, this means the processes in the container can use We set memory limit only, this means the processes in the container can use
@@ -430,7 +430,7 @@ We set memory limit only, this means the processes in the container can use
would be 2*300M, so processes can use 300M swap memory as well. would be 2*300M, so processes can use 300M swap memory as well.
```console ```console
$ docker run -it -m 300M --memory-swap 1G ubuntu:24.04 /bin/bash $ docker run -it -m 300M --memory-swap 1G ubuntu:26.04 /bin/bash
``` ```
We set both memory and swap memory, so the processes in the container can use We set both memory and swap memory, so the processes in the container can use
@@ -456,7 +456,7 @@ The following example limits the memory (`-m`) to 500M and sets the memory
reservation to 200M. reservation to 200M.
```console ```console
$ docker run -it -m 500M --memory-reservation 200M ubuntu:24.04 /bin/bash $ docker run -it -m 500M --memory-reservation 200M ubuntu:26.04 /bin/bash
``` ```
Under this configuration, when the container consumes memory more than 200M and Under this configuration, when the container consumes memory more than 200M and
@@ -466,7 +466,7 @@ memory below 200M.
The following example set memory reservation to 1G without a hard memory limit. The following example set memory reservation to 1G without a hard memory limit.
```console ```console
$ docker run -it --memory-reservation 1G ubuntu:24.04 /bin/bash $ docker run -it --memory-reservation 1G ubuntu:26.04 /bin/bash
``` ```
The container can use as much memory as it needs. The memory reservation setting The container can use as much memory as it needs. The memory reservation setting
@@ -484,13 +484,13 @@ The following example limits the memory to 100M and disables the OOM killer for
this container: this container:
```console ```console
$ docker run -it -m 100M --oom-kill-disable ubuntu:24.04 /bin/bash $ docker run -it -m 100M --oom-kill-disable ubuntu:26.04 /bin/bash
``` ```
The following example, illustrates a dangerous way to use the flag: The following example, illustrates a dangerous way to use the flag:
```console ```console
$ docker run -it --oom-kill-disable ubuntu:24.04 /bin/bash $ docker run -it --oom-kill-disable ubuntu:26.04 /bin/bash
``` ```
The container has unlimited memory which can cause the host to run out memory The container has unlimited memory which can cause the host to run out memory
@@ -510,7 +510,7 @@ between 0 and 100. A value of 0 turns off anonymous page swapping. A value of
For example, you can set: For example, you can set:
```console ```console
$ docker run -it --memory-swappiness=0 ubuntu:24.04 /bin/bash $ docker run -it --memory-swappiness=0 ubuntu:26.04 /bin/bash
``` ```
Setting the `--memory-swappiness` option is helpful when you want to retain the Setting the `--memory-swappiness` option is helpful when you want to retain the
@@ -561,7 +561,7 @@ And usually `--cpu-period` should work with `--cpu-quota`.
Examples: Examples:
```console ```console
$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:24.04 /bin/bash $ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:26.04 /bin/bash
``` ```
If there is 1 CPU, this means the container can get 50% CPU worth of run-time every 50ms. If there is 1 CPU, this means the container can get 50% CPU worth of run-time every 50ms.
@@ -582,13 +582,13 @@ We can set cpus in which to allow execution for containers.
Examples: Examples:
```console ```console
$ docker run -it --cpuset-cpus="1,3" ubuntu:24.04 /bin/bash $ docker run -it --cpuset-cpus="1,3" ubuntu:26.04 /bin/bash
``` ```
This means processes in container can be executed on cpu 1 and cpu 3. This means processes in container can be executed on cpu 1 and cpu 3.
```console ```console
$ docker run -it --cpuset-cpus="0-2" ubuntu:24.04 /bin/bash $ docker run -it --cpuset-cpus="0-2" ubuntu:26.04 /bin/bash
``` ```
This means processes in container can be executed on cpu 0, cpu 1 and cpu 2. This means processes in container can be executed on cpu 0, cpu 1 and cpu 2.
@@ -599,14 +599,14 @@ on NUMA systems.
Examples: Examples:
```console ```console
$ docker run -it --cpuset-mems="1,3" ubuntu:24.04 /bin/bash $ docker run -it --cpuset-mems="1,3" ubuntu:26.04 /bin/bash
``` ```
This example restricts the processes in the container to only use memory from This example restricts the processes in the container to only use memory from
memory nodes 1 and 3. memory nodes 1 and 3.
```console ```console
$ docker run -it --cpuset-mems="0-2" ubuntu:24.04 /bin/bash $ docker run -it --cpuset-mems="0-2" ubuntu:26.04 /bin/bash
``` ```
This example restricts the processes in the container to only use memory from This example restricts the processes in the container to only use memory from
@@ -637,8 +637,8 @@ For example, the commands below create two containers with different blkio
weight: weight:
```console ```console
$ docker run -it --name c1 --blkio-weight 300 ubuntu:24.04 /bin/bash $ docker run -it --name c1 --blkio-weight 300 ubuntu:26.04 /bin/bash
$ docker run -it --name c2 --blkio-weight 600 ubuntu:24.04 /bin/bash $ docker run -it --name c2 --blkio-weight 600 ubuntu:26.04 /bin/bash
``` ```
If you do block IO in the two containers at the same time, by, for example: If you do block IO in the two containers at the same time, by, for example:
@@ -854,11 +854,11 @@ For interacting with the network stack, instead of using `--privileged` they
should use `--cap-add=NET_ADMIN` to modify the network interfaces. should use `--cap-add=NET_ADMIN` to modify the network interfaces.
```console ```console
$ docker run -it --rm ubuntu:24.04 ip link add dummy0 type dummy $ docker run -it --rm ubuntu:26.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted RTNETLINK answers: Operation not permitted
$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:24.04 ip link add dummy0 type dummy $ docker run -it --rm --cap-add=NET_ADMIN ubuntu:26.04 ip link add dummy0 type dummy
``` ```
To mount a FUSE based filesystem, you need to combine both `--cap-add` and To mount a FUSE based filesystem, you need to combine both `--cap-add` and
+16
View File
@@ -62,6 +62,22 @@ func TestNonexistingHelp(t *testing.T) {
}) })
} }
// TestNonexistingVersion ensures correct behaviour when invoking a
// nonexistent plugin with `--version`.
func TestNonexistingVersion(t *testing.T) {
run, _, cleanup := prepare(t)
defer cleanup()
for _, flag := range []string{"--version", "-v"} {
res := icmd.RunCmd(run("nonexistent", flag))
res.Assert(t, icmd.Expected{
ExitCode: 1,
Out: icmd.None,
})
golden.Assert(t, res.Stderr(), "docker-nonexistent-err.golden")
}
}
// TestRunBad ensures correct behaviour when running an existent but invalid plugin // TestRunBad ensures correct behaviour when running an existent but invalid plugin
func TestRunBad(t *testing.T) { func TestRunBad(t *testing.T) {
run, _, cleanup := prepare(t) run, _, cleanup := prepare(t)
+1 -1
View File
@@ -30,5 +30,5 @@ func TestOauthLogin(t *testing.T) {
assert.NilError(t, err) assert.NilError(t, err)
output, _ := io.ReadAll(p) output, _ := io.ReadAll(p)
assert.Check(t, strings.Contains(string(output), "USING WEB-BASED LOGIN"), string(output)) assert.Check(t, strings.Contains(string(output), "Using web-based login"), string(output))
} }
+27 -14
View File
@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"os/exec"
"strings" "strings"
"github.com/docker/cli/cli/config/credentials" "github.com/docker/cli/cli/config/credentials"
@@ -17,8 +18,6 @@ import (
"github.com/docker/cli/internal/registry" "github.com/docker/cli/internal/registry"
"github.com/docker/cli/internal/tui" "github.com/docker/cli/internal/tui"
"github.com/morikuni/aec" "github.com/morikuni/aec"
"github.com/sirupsen/logrus"
"github.com/pkg/browser" "github.com/pkg/browser"
) )
@@ -83,19 +82,18 @@ var ErrDeviceLoginStartFail = errors.New("failed to start device code flow login
// The retrieved tokens are stored in the credentials store (under a separate // The retrieved tokens are stored in the credentials store (under a separate
// key), and the refresh token is concatenated with the client ID. // key), and the refresh token is concatenated with the client ID.
func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.AuthConfig, error) { func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.AuthConfig, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
state, err := m.api.GetDeviceCode(ctx, m.audience) state, err := m.api.GetDeviceCode(ctx, m.audience)
if err != nil { if err != nil {
logrus.Debugf("failed to start device code login: %v", err) return nil, fmt.Errorf("%w: %w", ErrDeviceLoginStartFail, err)
return nil, ErrDeviceLoginStartFail
} }
if state.UserCode == "" { if state.UserCode == "" {
logrus.Debugf("failed to start device code login: missing user code") return nil, fmt.Errorf("%w: missing user code", ErrDeviceLoginStartFail)
return nil, ErrDeviceLoginStartFail
} }
_, _ = fmt.Fprintln(w, aec.Bold.Apply("\nUSING WEB-BASED LOGIN"))
var out tui.Output var out tui.Output
switch stream := w.(type) { switch stream := w.(type) {
case *streams.Out: case *streams.Out:
@@ -103,9 +101,10 @@ func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.Aut
default: default:
out = tui.NewOutput(streams.NewOut(w)) out = tui.NewOutput(streams.NewOut(w))
} }
out.PrintNote("To sign in with credentials on the command line, use 'docker login -u <username>'\n") out.PrintNote("Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'\n")
_, _ = fmt.Fprintf(w, "\nYour one-time device confirmation code is: "+aec.Bold.Apply("%s\n"), state.UserCode) _, _ = fmt.Fprintln(w, "Your one-time device confirmation code is:", aec.Bold.Apply(state.UserCode))
_, _ = fmt.Fprintf(w, aec.Bold.Apply("Press ENTER")+" to open your browser or submit your device code here: "+aec.Underline.Apply("%s\n"), strings.Split(state.VerificationURI, "?")[0]) _, _ = fmt.Fprintln(w, "Open this URL to authenticate:", aec.Underline.Apply(state.VerificationURI))
_, _ = fmt.Fprintln(w, "\n"+aec.Bold.Apply("Press ENTER")+" to open the URL in your browser, or "+aec.Bold.Apply("Ctrl+C")+" to cancel.")
tokenResChan := make(chan api.TokenResponse) tokenResChan := make(chan api.TokenResponse)
waitForTokenErrChan := make(chan error) waitForTokenErrChan := make(chan error)
@@ -120,11 +119,25 @@ func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.Aut
go func() { go func() {
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
_, _ = reader.ReadString('\n') if _, err := reader.ReadString('\n'); err != nil || ctx.Err() != nil {
_ = m.openBrowser(state.VerificationURI) return
}
err := m.openBrowser(state.VerificationURI)
if ctx.Err() != nil {
return
}
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
_, _ = fmt.Fprintln(w, "No browser found. Open the URL above manually to continue.")
} else {
_, _ = fmt.Fprintln(w, "Failed to open browser:", err)
_, _ = fmt.Fprintln(w, "Open the URL above manually to continue.")
}
return
}
_, _ = fmt.Fprintln(w, "\nOpening browser…")
}() }()
_, _ = fmt.Fprint(w, "\nWaiting for authentication in the browser…\n")
var tokenRes api.TokenResponse var tokenRes api.TokenResponse
select { select {
case <-ctx.Done(): case <-ctx.Done():
+2 -2
View File
@@ -69,10 +69,10 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
// get the http transport, this will be used in a client to upload manifest // get the http transport, this will be used in a client to upload manifest
base := &http.Transport{ base := &http.Transport{
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{ DialContext: (&net.Dialer{
Timeout: 30 * time.Second, Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second, KeepAlive: 30 * time.Second,
}).Dial, }).DialContext,
TLSHandshakeTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: endpoint.TLSConfig, TLSClientConfig: endpoint.TLSConfig,
DisableKeepAlives: true, DisableKeepAlives: true,
+6 -3
View File
@@ -27,8 +27,13 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
})) }))
cli.SetOut(outStream) cli.SetOut(outStream)
r, _, err := os.Pipe() r, w, err := os.Pipe()
assert.NilError(t, err) assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r)) cli.SetIn(streams.NewIn(r))
notifyCtx, notifyCancel := context.WithCancel(ctx) notifyCtx, notifyCancel := context.WithCancel(ctx)
@@ -58,8 +63,6 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
}() }()
} }
assert.Check(t, cli.OutBuffer().Len() > 0)
// a small delay to ensure the plugin is prompting // a small delay to ensure the plugin is prompting
time.Sleep(100 * time.Microsecond) time.Sleep(100 * time.Microsecond)
+14 -6
View File
@@ -83,16 +83,24 @@ set as the **URL**, the repository is cloned locally and then sent as the contex
Add a line to /etc/hosts. The format is hostname=ip, or hostname:ip. Add a line to /etc/hosts. The format is hostname=ip, or hostname:ip.
The **--add-host** option can be set multiple times. The **--add-host** option can be set multiple times.
**--build-arg** *variable* **--build-arg** *name*[=*value*]
name and value of a **buildarg**. Set a build-time variable. The *name* is the variable name, as declared
by an `ARG` instruction in the Dockerfile. If *value* is omitted, the
value of the variable *name* from the local environment is used; if it is
not set there either, the default from the `ARG` instruction (if any) is
used.
Build-time variables are available as environment variables to commands
run by the Dockerfile's `RUN` instructions, and can be used for variable
expansion in other Dockerfile instructions. An environment variable defined
by an `ENV` instruction always overrides an `ARG` of the same name. This
mechanism is not meant for passing secret values.
For example, if you want to pass a value for `http_proxy`, use For example, if you want to pass a value for `http_proxy`, use
`--build-arg=http_proxy="http://some.proxy.url"` `--build-arg=http_proxy="http://some.proxy.url"`
Users pass these values at build-time. Docker uses the `buildargs` as the See also https://docs.docker.com/reference/dockerfile/#arg and
environment context for command(s) run via the Dockerfile's `RUN` instruction https://docs.docker.com/reference/cli/docker/buildx/build/#build-arg.
or for variable expansion in other Dockerfile instructions. This is not meant
for passing secret values. [Read more about the buildargs instruction](https://docs.docker.com/engine/reference/builder/#arg)
**--cache-from** "" **--cache-from** ""
Set image that will be used as a build cache source. Set image that will be used as a build cache source.
+2 -2
View File
@@ -48,10 +48,10 @@ Valid placeholders for the Go template are listed below:
$ docker container ls -a $ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a87ecb4f327c ubuntu:24.04 /bin/sh -c #(nop) MA 20 minutes ago Exit 0 desperate_brattain a87ecb4f327c ubuntu:26.04 /bin/sh -c #(nop) MA 20 minutes ago Exit 0 desperate_brattain
01946d9d34d8 busybox /bin/sh -c #(nop) MA 33 minutes ago Exit 0 thirsty_bell 01946d9d34d8 busybox /bin/sh -c #(nop) MA 33 minutes ago Exit 0 thirsty_bell
c1d3b0166030 acffc0358b9e /bin/sh -c yum -y up 2 weeks ago Exit 1 determined_torvalds c1d3b0166030 acffc0358b9e /bin/sh -c yum -y up 2 weeks ago Exit 1 determined_torvalds
41d50ecd2f57 ubuntu:24.04 /bin/sh -c #(nop) MA 2 weeks ago Exit 0 drunk_pike 41d50ecd2f57 ubuntu:26.04 /bin/sh -c #(nop) MA 2 weeks ago Exit 0 drunk_pike
## Display only IDs of all containers, including non-running ## Display only IDs of all containers, including non-running
+1 -1
View File
@@ -10,7 +10,7 @@ The title REPOSITORY for the first title may seem confusing. It is essentially
the image name. However, because you can tag a specific image, and multiple tags the image name. However, because you can tag a specific image, and multiple tags
(image instances) can be associated with a single name, the name is really a (image instances) can be associated with a single name, the name is really a
repository for all tagged images of the same name. For example consider an image repository for all tagged images of the same name. For example consider an image
called ubuntu. It may be tagged with 24.04 or 22.04, etc. to manage different called ubuntu. It may be tagged with 26.04 or 24.04, etc. to manage different
versions. versions.
## Filters ## Filters
+19 -19
View File
@@ -27,17 +27,17 @@ Docker Engine uses the `:latest` tag as a default. This example pulls the
Docker images can consist of multiple layers. In the example above, the image Docker images can consist of multiple layers. In the example above, the image
consists of a single layer; `e756f3fdd6a3`. consists of a single layer; `e756f3fdd6a3`.
Layers can be reused by images. For example, the `debian:bookworm` image shares Layers can be reused by images. For example, the `debian:trixie` image shares
its layer with the `debian:latest`. Pulling the `debian:bookworm` image therefore its layer with the `debian:latest`. Pulling the `debian:trixie` image therefore
only pulls its metadata, but not its layers, because the layer is already present only pulls its metadata, but not its layers, because the layer is already present
locally: locally:
$ docker image pull debian:bookworm $ docker image pull debian:trixie
bookworm: Pulling from library/debian trixie: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510 Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:bookworm Status: Downloaded newer image for debian:trixie
docker.io/library/debian:bookworm docker.io/library/debian:trixie
To see which images are present locally, use the **docker-images(1)** To see which images are present locally, use the **docker-images(1)**
command: command:
@@ -45,12 +45,12 @@ command:
$ docker images $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
debian bookworm 4eacea30377a 8 days ago 124MB debian trixie 4eacea30377a 8 days ago 124MB
debian latest 4eacea30377a 8 days ago 124MB debian latest 4eacea30377a 8 days ago 124MB
Docker uses a content-addressable image store, and the image ID is a SHA256 Docker uses a content-addressable image store, and the image ID is a SHA256
digest covering the image's configuration and layers. In the example above, digest covering the image's configuration and layers. In the example above,
`debian:bookworm` and `debian:latest` have the same image ID because they are `debian:trixie` and `debian:latest` have the same image ID because they are
the *same* image tagged with different names. Because they are the same image, the *same* image tagged with different names. Because they are the same image,
their layers are stored only once and do not consume extra disk space. their layers are stored only once and do not consume extra disk space.
@@ -64,8 +64,8 @@ in the online documentation.
So far, you've pulled images by their name (and "tag"). Using names and tags is So far, you've pulled images by their name (and "tag"). Using names and tags is
a convenient way to work with images. When using tags, you can `docker image pull` an a convenient way to work with images. When using tags, you can `docker image pull` an
image again to make sure you have the most up-to-date version of that image. image again to make sure you have the most up-to-date version of that image.
For example, `docker image pull ubuntu:24.04` pulls the latest version of the Ubuntu For example, `docker image pull ubuntu:26.04` pulls the latest version of the Ubuntu
24.04 image. 26.04 image.
In some cases you don't want images to be updated to newer versions, but prefer In some cases you don't want images to be updated to newer versions, but prefer
to use a fixed version of an image. Docker enables you to pull an image by its to use a fixed version of an image. Docker enables you to pull an image by its
@@ -74,15 +74,15 @@ of an image to pull. Doing so, allows you to "pin" an image to that version,
and guarantee that the image you're using is always the same. and guarantee that the image you're using is always the same.
To know the digest of an image, pull the image first. Let's pull the latest To know the digest of an image, pull the image first. Let's pull the latest
`ubuntu:24.04` image from Docker Hub: `ubuntu:26.04` image from Docker Hub:
$ docker image pull ubuntu:24.04 $ docker image pull ubuntu:26.04
24.04: Pulling from library/ubuntu 26.04: Pulling from library/ubuntu
125a6e411906: Pull complete 125a6e411906: Pull complete
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30 Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:24.04 Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:24.04 docker.io/library/ubuntu:26.04
Docker prints the digest of the image after the pull has finished. In the example Docker prints the digest of the image after the pull has finished. In the example
above, the digest of the image is: above, the digest of the image is:
@@ -159,11 +159,11 @@ images that are present locally:
$ docker image ls --filter reference=ubuntu $ docker image ls --filter reference=ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 8a3cdc4d1ad3 3 weeks ago 77.9MB ubuntu 24.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu jammy 8a3cdc4d1ad3 3 weeks ago 77.9MB ubuntu noble 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 24.04 35a88802559d 6 weeks ago 78.1MB ubuntu 26.04 35a88802559d 6 weeks ago 78.1MB
ubuntu latest 35a88802559d 6 weeks ago 78.1MB ubuntu latest 35a88802559d 6 weeks ago 78.1MB
ubuntu noble 35a88802559d 6 weeks ago 78.1MB ubuntu resolute 35a88802559d 6 weeks ago 78.1MB
## Cancel a pull ## Cancel a pull
+9 -9
View File
@@ -62,8 +62,8 @@ The following example outputs all events that were generated in the last 3 minut
relative to the current time on the client machine: relative to the current time on the client machine:
# docker events --since '3m' # docker events --since '3m'
2015-05-12T11:51:30.999999999Z07:00 4386fb97867d: (from ubuntu:24.04) die 2015-05-12T11:51:30.999999999Z07:00 4386fb97867d: (from ubuntu:26.04) die
2015-05-12T15:52:12.999999999Z07:00 4386fb97867d: (from ubuntu:24.04) stop 2015-05-12T15:52:12.999999999Z07:00 4386fb97867d: (from ubuntu:26.04) stop
2015-05-12T15:53:45.999999999Z07:00 7805c1d35632: (from redis:7.2) die 2015-05-12T15:53:45.999999999Z07:00 7805c1d35632: (from redis:7.2) die
2015-05-12T15:54:03.999999999Z07:00 7805c1d35632: (from redis:7.2) stop 2015-05-12T15:54:03.999999999Z07:00 7805c1d35632: (from redis:7.2) stop
@@ -97,21 +97,21 @@ Lines. For information about JSON Lines, refer to https://jsonlines.org .
## Filters ## Filters
$ docker events --filter 'event=stop' $ docker events --filter 'event=stop'
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
2014-09-03T17:42:14.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2) 2014-09-03T17:42:14.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2)
$ docker events --filter 'image=ubuntu:24.04' $ docker events --filter 'image=ubuntu:26.04'
2014-05-10T17:42:14.999999999Z07:00 container start 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container start 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container die 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
$ docker events --filter 'container=7805c1d35632' $ docker events --filter 'container=7805c1d35632'
2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (image=redis:7.2) 2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (image=redis:7.2)
2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image= redis:7.2) 2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image= redis:7.2)
$ docker events --filter 'container=7805c1d35632' --filter 'container=4386fb97867d' $ docker events --filter 'container=7805c1d35632' --filter 'container=4386fb97867d'
2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04) 2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04) 2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (image=redis:7.2) 2014-05-10T17:42:14.999999999Z07:00 container die 7805c1d35632 (image=redis:7.2)
2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2) 2014-09-03T15:49:29.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2)
+2 -2
View File
@@ -71,8 +71,8 @@ Server:
seccomp seccomp
Profile: builtin Profile: builtin
cgroupns cgroupns
Kernel Version: 5.15.0-25-generic Kernel Version: 6.8.0-31-generic
Operating System: Ubuntu 22.04 LTS Operating System: Ubuntu 24.04 LTS
OSType: linux OSType: linux
Architecture: x86_64 Architecture: x86_64
CPUs: 1 CPUs: 1
+3 -11
View File
@@ -33,8 +33,6 @@ func parseCount(s string) (int, error) {
} }
// Set a new mount value // Set a new mount value
//
//nolint:gocyclo
func (o *GpuOpts) Set(value string) error { func (o *GpuOpts) Set(value string) error {
csvReader := csv.NewReader(strings.NewReader(value)) csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read() fields, err := csvReader.Read()
@@ -48,20 +46,14 @@ func (o *GpuOpts) Set(value string) error {
// Set writable as the default // Set writable as the default
for _, field := range fields { for _, field := range fields {
key, val, withValue := strings.Cut(field, "=") key, val, withValue := strings.Cut(field, "=")
if !withValue {
key, val = "count", key
}
if _, ok := seen[key]; ok { if _, ok := seen[key]; ok {
return fmt.Errorf("gpu request key '%s' can be specified only once", key) return fmt.Errorf("gpu request key '%s' can be specified only once", key)
} }
seen[key] = struct{}{} seen[key] = struct{}{}
if !withValue {
seen["count"] = struct{}{}
req.Count, err = parseCount(key)
if err != nil {
return err
}
continue
}
switch key { switch key {
case "driver": case "driver":
req.Driver = val req.Driver = val
+10
View File
@@ -52,3 +52,13 @@ func TestGpusOpts(t *testing.T) {
})) }))
} }
} }
func TestGpusOptDuplicateCount(t *testing.T) {
for _, value := range []string{"count=1,2", "1,2", "all,1", "count=1,all", "1,count=2", "count=1,count=2"} {
t.Run(value, func(t *testing.T) {
var gpus GpuOpts
assert.Error(t, gpus.Set(value), "gpu request key 'count' can be specified only once")
assert.Assert(t, is.Len(gpus.Value(), 0))
})
}
}
+15 -8
View File
@@ -88,13 +88,20 @@ if [ "$CGO_ENABLED" = "1" ] && [ "$(go env GOOS)" != "windows" ]; then
fi fi
export GO_BUILDMODE export GO_BUILDMODE
GO_LDFLAGS="${GO_LDFLAGS:-}" # Omit DWARF debug information to reduce binary size, but retain the symbol
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.GitCommit=${GITCOMMIT}\"" # table for tools that inspect Go binaries. Pass GO_LDFLAGS="-w=0" to retain DWARF.
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.BuildTime=${BUILDTIME}\"" GO_LDFLAGS="-w ${GO_LDFLAGS:-}"
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.Version=${VERSION}\""
if test -n "${PLATFORM}"; then # Quotes are interpreted by Go's -ldflags parser, not the shell.
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.PlatformName=${PLATFORM}\"" # shellcheck disable=SC2089
fi {
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.GitCommit=${GITCOMMIT}\""
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.BuildTime=${BUILDTIME}\""
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.Version=${VERSION}\""
if test -n "${PLATFORM}"; then
GO_LDFLAGS="$GO_LDFLAGS -X \"github.com/docker/cli/cli/version.PlatformName=${PLATFORM}\""
fi
}
if [ "$CGO_ENABLED" = "1" ] && [ "$GO_LINKMODE" = "static" ] && [ "$(go env GOOS)" = "linux" ]; then if [ "$CGO_ENABLED" = "1" ] && [ "$GO_LINKMODE" = "static" ] && [ "$(go env GOOS)" = "linux" ]; then
GO_LDFLAGS="$GO_LDFLAGS -linkmode external -extldflags -static" GO_LDFLAGS="$GO_LDFLAGS -linkmode external -extldflags -static"
fi fi
@@ -128,7 +135,7 @@ if [ -n "$GO_STRIP" ]; then
# /usr/local/go/pkg/tool/linux_amd64/link: /usr/local/go/pkg/tool/linux_amd64/link: running strip failed: exit status 1 # /usr/local/go/pkg/tool/linux_amd64/link: /usr/local/go/pkg/tool/linux_amd64/link: running strip failed: exit status 1
# llvm-strip: error: unsupported load command (cmd=0x5) # llvm-strip: error: unsupported load command (cmd=0x5)
# more info: https://github.com/docker/cli/pull/3717 # more info: https://github.com/docker/cli/pull/3717
GO_LDFLAGS="$GO_LDFLAGS -s -w" GO_LDFLAGS="$GO_LDFLAGS -s"
fi fi
export GO_LDFLAGS="$GO_LDFLAGS" # https://github.com/koalaman/shellcheck/issues/2064 export GO_LDFLAGS="$GO_LDFLAGS" # https://github.com/koalaman/shellcheck/issues/2064
+28 -27
View File
@@ -21,11 +21,11 @@ require (
github.com/distribution/reference v0.6.0 github.com/distribution/reference v0.6.0
github.com/docker/cli-docs-tool v0.11.0 github.com/docker/cli-docs-tool v0.11.0
github.com/docker/distribution v2.8.3+incompatible github.com/docker/distribution v2.8.3+incompatible
github.com/docker/docker-credential-helpers v0.9.9 github.com/docker/docker-credential-helpers v0.9.12
github.com/docker/go-connections v0.8.2 github.com/docker/go-connections v0.8.2
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
github.com/fvbommel/sortorder v1.2.0 github.com/fvbommel/sortorder v1.2.1
github.com/go-jose/go-jose/v4 v4.1.5 github.com/go-jose/go-jose/v4 v4.1.7
github.com/go-viper/mapstructure/v2 v2.5.0 github.com/go-viper/mapstructure/v2 v2.5.0
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
@@ -33,12 +33,12 @@ require (
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/mattn/go-runewidth v0.0.31 github.com/mattn/go-runewidth v0.0.31
github.com/moby/go-archive v0.3.3 github.com/moby/go-archive v0.3.3
github.com/moby/moby/api v1.56.1 github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131
github.com/moby/moby/client v0.6.2 github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131
github.com/moby/patternmatcher v0.6.1 github.com/moby/patternmatcher v0.6.1
github.com/moby/swarmkit/v2 v2.1.2 github.com/moby/swarmkit/v2 v2.1.3
github.com/moby/sys/atomicwriter v0.1.0 github.com/moby/sys/atomicwriter v0.1.0
github.com/moby/sys/capability v0.4.0 github.com/moby/sys/capability v0.5.0
github.com/moby/sys/sequential v0.7.0 github.com/moby/sys/sequential v0.7.0
github.com/moby/sys/signal v0.7.1 github.com/moby/sys/signal v0.7.1
github.com/moby/sys/symlink v0.3.0 github.com/moby/sys/symlink v0.3.0
@@ -52,25 +52,25 @@ require (
github.com/spf13/cobra v1.10.2 github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10 github.com/spf13/pflag v1.0.10
github.com/tonistiigi/go-rosetta v0.0.0-20220804170347-3f4430f2d346 github.com/tonistiigi/go-rosetta v0.0.0-20220804170347-3f4430f2d346
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0
go.opentelemetry.io/otel v1.46.0 go.opentelemetry.io/otel v1.47.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0
go.opentelemetry.io/otel/metric v1.46.0 go.opentelemetry.io/otel/metric v1.47.0
go.opentelemetry.io/otel/sdk v1.46.0 go.opentelemetry.io/otel/sdk v1.47.0
go.opentelemetry.io/otel/sdk/metric v1.46.0 go.opentelemetry.io/otel/sdk/metric v1.47.0
go.opentelemetry.io/otel/trace v1.46.0 go.opentelemetry.io/otel/trace v1.47.0
go.yaml.in/yaml/v3 v3.0.5 go.yaml.in/yaml/v3 v3.0.6
golang.org/x/sync v0.23.0 golang.org/x/sync v0.25.0
golang.org/x/sys v0.48.0 golang.org/x/sys v0.50.0
golang.org/x/term v0.46.0 golang.org/x/term v0.48.0
golang.org/x/text v0.42.0 golang.org/x/text v0.44.0
gotest.tools/v3 v3.5.2 gotest.tools/v3 v3.5.2
tags.cncf.io/container-device-interface v1.1.1 tags.cncf.io/container-device-interface v1.1.1
) )
require ( require (
github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 // indirect github.com/Azure/go-ansiterm v0.0.0-20261013165250-51075c6ea6bc // indirect
github.com/Microsoft/go-winio v0.6.3 // indirect github.com/Microsoft/go-winio v0.6.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect
@@ -87,7 +87,7 @@ require (
github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/mux v1.8.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.20.1 // indirect github.com/klauspost/compress v1.20.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/user v0.4.1 // indirect github.com/moby/sys/user v0.4.1 // indirect
github.com/moby/sys/userns v0.2.1 // indirect github.com/moby/sys/userns v0.2.1 // indirect
@@ -99,13 +99,14 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
go.etcd.io/raft/v3 v3.6.0 // indirect go.etcd.io/raft/v3 v3.6.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 // indirect
go.opentelemetry.io/otel/log v1.47.0 // indirect
go.opentelemetry.io/proto/otlp v1.11.0 // indirect go.opentelemetry.io/proto/otlp v1.11.0 // indirect
golang.org/x/mod v0.41.0 // indirect golang.org/x/mod v0.43.0 // indirect
golang.org/x/net v0.60.0 // indirect golang.org/x/net v0.62.0 // indirect
golang.org/x/time v0.16.0 // indirect golang.org/x/time v0.16.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc // indirect
google.golang.org/grpc v1.83.2 // indirect google.golang.org/grpc v1.83.2 // indirect
google.golang.org/protobuf v1.36.12 // indirect google.golang.org/protobuf v1.36.12 // indirect
) )
+58 -58
View File
@@ -2,8 +2,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 h1:m2xcjRABtG288vnlV3U/PKh/HnPURxZp50RKNUwBxM8= github.com/Azure/go-ansiterm v0.0.0-20261013165250-51075c6ea6bc h1:58s5YzGPNAP7+e1uemaL0ax/NPSeJOHdRpRIowd+JDk=
github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4/go.mod h1:MTUE7ZuZO89FAtAwozGg6AWD83pcdefnEq5gF82MB8s= github.com/Azure/go-ansiterm v0.0.0-20261013165250-51075c6ea6bc/go.mod h1:DMNF6Kxv+EcuUvVuNkvC3f+BjEEmc/Fn9aU+qiD8zpU=
github.com/Microsoft/go-winio v0.6.3 h1:M/52tsoyTfwaxajLnXZm7PqkbMGRH8iSWP+8fcg9MQ4= github.com/Microsoft/go-winio v0.6.3 h1:M/52tsoyTfwaxajLnXZm7PqkbMGRH8iSWP+8fcg9MQ4=
github.com/Microsoft/go-winio v0.6.3/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg= github.com/Microsoft/go-winio v0.6.3/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -35,8 +35,8 @@ github.com/docker/cli-docs-tool v0.11.0 h1:7d8QARFb7QEobizqxmEM7fOteZEHwH/zWgHQt
github.com/docker/cli-docs-tool v0.11.0/go.mod h1:ma8BKiisUo8D6W05XEYIh3oa1UbgrZhi1nowyKFJa8Q= github.com/docker/cli-docs-tool v0.11.0/go.mod h1:ma8BKiisUo8D6W05XEYIh3oa1UbgrZhi1nowyKFJa8Q=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= 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/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.9 h1:BkydjIgZ46JnDbqyM2p2fc63KMw6y+KHL3Em/2AGJ7w= github.com/docker/docker-credential-helpers v0.9.12 h1:hAgjJcMuC17DPf0Kl/HQSZQ7cxVo+wEA8Oo1SzkmqFg=
github.com/docker/docker-credential-helpers v0.9.9/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/docker-credential-helpers v0.9.12/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
github.com/docker/go-connections v0.8.2 h1:9d9DEokx5W7qlr0shkFXIxEA7+TTD+llwzcykSlxMNc= github.com/docker/go-connections v0.8.2 h1:9d9DEokx5W7qlr0shkFXIxEA7+TTD+llwzcykSlxMNc=
github.com/docker/go-connections v0.8.2/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-connections v0.8.2/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
github.com/docker/go-events v0.1.0 h1:J8VX4H7Ta8mmBhv/K/24x1kosKOrEEnYmGjcdFHTOW0= github.com/docker/go-events v0.1.0 h1:J8VX4H7Ta8mmBhv/K/24x1kosKOrEEnYmGjcdFHTOW0=
@@ -49,10 +49,10 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc=
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
github.com/fvbommel/sortorder v1.2.0 h1:TRIiRiGX+djh3Yf4FVxmWmAcYfIr5dH0NbzJWOSAWZk= github.com/fvbommel/sortorder v1.2.1 h1:ASc85RbthwLEqzuiCk7WQQiopfyGWQiEYZVJ3Qa4A+U=
github.com/fvbommel/sortorder v1.2.0/go.mod h1:LbhO04ijZIeUuvz9B9BkI/qYrpZZEn1gWhxv4QjUKVs= github.com/fvbommel/sortorder v1.2.1/go.mod h1:LbhO04ijZIeUuvz9B9BkI/qYrpZZEn1gWhxv4QjUKVs=
github.com/go-jose/go-jose/v4 v4.1.5 h1:RjgjO2LOtWOJKUC5wpwY9LR3B3vwVAz6JS2YHfYU6eA= github.com/go-jose/go-jose/v4 v4.1.7 h1:Nac/98uT5LPkfbiFuYa8ktf62a2VxwQ4xbq1GK8pV5E=
github.com/go-jose/go-jose/v4 v4.1.5/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-jose/go-jose/v4 v4.1.7/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -78,8 +78,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= github.com/klauspost/compress v1.20.2 h1:v5tiZvm1KGLyg5d5oXdXe3lsSPrbEUiKoXGia//I7Qo=
github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/compress v1.20.2/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5IBgwo= github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5IBgwo=
@@ -88,18 +88,18 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME= github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME=
github.com/moby/go-archive v0.3.3/go.mod h1:Npdv43fFqlhZW7Xo8fbm3ZMYFvAGNviUPqX21VERbcE= github.com/moby/go-archive v0.3.3/go.mod h1:Npdv43fFqlhZW7Xo8fbm3ZMYFvAGNviUPqX21VERbcE=
github.com/moby/moby/api v1.56.1 h1:PpWkvVPB7Fr/No8w+TfyJ/I6rWZ2YPZhT3JorIg+06c= github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131 h1:tPz9ahj8F7AjQw62XQFP65kmoxF3rXTYSit3q06/yQc=
github.com/moby/moby/api v1.56.1/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131/go.mod h1:pRZ1QRtx6AVhdckeFYo4DUX4ASNF0SCllhyY6aj2mgg=
github.com/moby/moby/client v0.6.2 h1:ekSPlMccrZGcw6Scb8T9D39qE0mB+XupU/yS0zNw9N4= github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131 h1:ReIO7lalQVE4BetZuIvrxScg8Rxv4Sk74XRs06ryRDU=
github.com/moby/moby/client v0.6.2/go.mod h1:DGcnO7qmPJrqobx/ggQgQ/AUk+2wgVdQv7uxB0/mEsc= github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131/go.mod h1:dPyRteJDuLdP8to3kWmNAU/tbMwSFCE88yKHvY/nZ9k=
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U= github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/swarmkit/v2 v2.1.2 h1:1WDZAI6HVYNKdCG4zlXnTAPyLsLwuhRGWlHoOUf5Z6I= github.com/moby/swarmkit/v2 v2.1.3 h1:UcwtwkIRjr75qSgUWCTIuzKUzAXlidxsiqVMnyxSF1w=
github.com/moby/swarmkit/v2 v2.1.2/go.mod h1:GQ6T0ij2oBbWX10OHwpvK449xfXkQMZ8J+B+eQ4mgp4= github.com/moby/swarmkit/v2 v2.1.3/go.mod h1:KhkxT93Hm4wHoNUPJ4JRD384pS7OODFGzJWoDRj9bLE=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= github.com/moby/sys/capability v0.5.0 h1:Bm4oD9xGCtZguPnaoQy1/jvKTSwZHMvM0FrnxNYtGYU=
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/capability v0.5.0/go.mod h1:i+0cXvNSriGrL3C6sxnmlmGL5HVU0OdxocizXdC8A+g=
github.com/moby/sys/mount v0.3.5 h1:eS3fsZTjHaBihwjp4/+5Z3jxqLXYsbwxqpVSfFv3M00= github.com/moby/sys/mount v0.3.5 h1:eS3fsZTjHaBihwjp4/+5Z3jxqLXYsbwxqpVSfFv3M00=
github.com/moby/sys/mount v0.3.5/go.mod h1:WUQDO+/uCiCIkIztx8SrwIDVn2dtMFRBebRhpDFT71M= github.com/moby/sys/mount v0.3.5/go.mod h1:WUQDO+/uCiCIkIztx8SrwIDVn2dtMFRBebRhpDFT71M=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
@@ -155,63 +155,65 @@ go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc= go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE= go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0 h1:qkDYCAFiZXLcs1L4aY+tP2wguQ4kURANqHOQMA2et2s= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0 h1:LaLVGJtIzHcvHjVs2OftmKcc+M9mdOqS8vZ1fBD1Yes=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0/go.mod h1:tkipS4DRzmpAmvg+Gw4++O1IdDq6TVDnvnYU6cmbQVs= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0/go.mod h1:vF6H5sNDuQBJWgSX00iZgbIqk2MZZoVMH0ar5t5bOpw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0 h1:w53CDeOA/Kurp7yRsegSr6pbbr759dOvJ+yNmWM6Hxs= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0 h1:UFpxOpYPmMNUtOWhdb+nC1WELIgVf8z9higURrbzYU4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0/go.mod h1:BOmGMCbAtvcJiSJ+hLuhgPLdDbimnraSl8irz3iY8sY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0/go.mod h1:YBGjxe3lt0jtXoEXxGrGhv/jM7oUBUDVK7zhAvNyEjc=
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8= go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o= go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
go.opentelemetry.io/otel/metric/x v0.68.0 h1:TA/cBT23D3MnxYPwHL7YFOdYGdx0A0v+s7Mzotpd1dU= go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
go.opentelemetry.io/otel/metric/x v0.68.0/go.mod h1:agudOmvWhwUTjgibWDzxD2PoWYnpw5Ht5jISYOD2Hd4= go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI= go.opentelemetry.io/otel/metric/x v0.69.0 h1:DjRLr15H83v+hCW7JA9NoJvOkYTtmq5YoDRbe9deYpM=
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM= go.opentelemetry.io/otel/metric/x v0.69.0/go.mod h1:uVvsMPMFFyj/HUQfrUnH3JjnOQ1dwFDorgFLRBasM0k=
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE= go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4= go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw=
go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM=
go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0=
go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk= go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk=
go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E= go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.6 h1:zcDfvjXEqTQmpjniUBLc91xYJMB2c4QOFxEF/LCEckM=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= go.yaml.in/yaml/v3 v3.0.6/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= golang.org/x/mod v0.43.0 h1:MFuq5J6s35W9D3IjkwyWc9vHh0nENOrt5K8Iof4ofmg=
golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= golang.org/x/mod v0.43.0/go.mod h1:4ec1JnuyBz5+FIVhg86UsA39YG8BpnrZdJYSNHmGzHY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= golang.org/x/net v0.62.0 h1:18ELalfM5+XNRwzM2nYqXsZQ9ByS1uhj2O/U7+5jqRY=
golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/net v0.62.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= golang.org/x/sync v0.25.0 h1:dJnifr0nMV8/SBnBvdo4eSGGnrc3O4FFx6IqvtLcmRs=
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sync v0.25.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= golang.org/x/sys v0.50.0 h1:dkKZEFTEKaLr1sjhs0WiKqoi8Jj5nHbS3Njmx1UoMJs=
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/sys v0.50.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= golang.org/x/term v0.48.0 h1:G6UU1eiSB8nl3DzeUGt7Mg+2SctI8tPS6Z5/mBt6cOk=
golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= golang.org/x/term v0.48.0/go.mod h1:BRDLHCZr2SUjIeBHHpRyQeC9xzSAVbzY2rvKgafnHf4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= golang.org/x/text v0.44.0 h1:YItdp/mQNGnsmrgpcdA5yQ3bnRxCfo/Tj/iByGW9GGo=
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/text v0.44.0/go.mod h1:S4FR1waQ9LbjQTls97SyRjDaUUVkaM+cXwwuG/G+MwY=
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE= golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s= golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -224,10 +226,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 h1:izFU9hz7aeLI/Mi1J0991ae+xcwRLr7hTqWnB/9aIIU= google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc h1:rZHRz0ogq4Pid1IKtA/ivHi8XONVF5tqUQXA2TtgpkE=
google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5/go.mod h1:3LhxRw4YYkf+ylAfgaY9JlVLFKhokkCV8duhLLe7+t0= google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:K/n0XLazCJHjD73YuMyNJsN38BPPy1kfFnKxUXaThFU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc= google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= google.golang.org/genproto/googleapis/rpc v0.0.0-20260928230214-8a89bd6388cc/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc=
google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=
google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
@@ -235,7 +237,5 @@ google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
tags.cncf.io/container-device-interface v1.1.1 h1:YPwQz4xg8PlQ0yT/baR0BtLpTQROe4l6M1yuRgAu1vc= tags.cncf.io/container-device-interface v1.1.1 h1:YPwQz4xg8PlQ0yT/baR0BtLpTQROe4l6M1yuRgAu1vc=
tags.cncf.io/container-device-interface v1.1.1/go.mod h1:S1PSJWYPD4Iom0/39mvr/VVFCfG0Yt14j20d0OYrY2M= tags.cncf.io/container-device-interface v1.1.1/go.mod h1:S1PSJWYPD4Iom0/39mvr/VVFCfG0Yt14j20d0OYrY2M=
+7 -5
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type csiEntryState struct { type csiEntryState struct {
baseState baseState
} }
@@ -13,11 +15,11 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
} }
switch { switch {
case sliceContains(alphabetics, b): case slices.Contains(alphabetics, b):
return csiState.parser.ground, nil return csiState.parser.ground, nil
case sliceContains(csiCollectables, b): case slices.Contains(csiCollectables, b):
return csiState.parser.csiParam, nil return csiState.parser.csiParam, nil
case sliceContains(executors, b): case slices.Contains(executors, b):
return csiState, csiState.parser.execute() return csiState, csiState.parser.execute()
} }
@@ -33,9 +35,9 @@ func (csiState csiEntryState) Transition(s state) error {
return csiState.parser.csiDispatch() return csiState.parser.csiDispatch()
case csiState.parser.csiParam: case csiState.parser.csiParam:
switch { switch {
case sliceContains(csiParams, csiState.parser.context.currentChar): case slices.Contains(csiParams, csiState.parser.context.currentChar):
_ = csiState.parser.collectParam() _ = csiState.parser.collectParam()
case sliceContains(intermeds, csiState.parser.context.currentChar): case slices.Contains(intermeds, csiState.parser.context.currentChar):
_ = csiState.parser.collectInter() _ = csiState.parser.collectInter()
} }
} }
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type csiParamState struct { type csiParamState struct {
baseState baseState
} }
@@ -13,11 +15,11 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
} }
switch { switch {
case sliceContains(alphabetics, b): case slices.Contains(alphabetics, b):
return csiState.parser.ground, nil return csiState.parser.ground, nil
case sliceContains(csiCollectables, b): case slices.Contains(csiCollectables, b):
return csiState, csiState.parser.collectParam() return csiState, csiState.parser.collectParam()
case sliceContains(executors, b): case slices.Contains(executors, b):
return csiState, csiState.parser.execute() return csiState, csiState.parser.execute()
} }
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type escapeIntermediateState struct { type escapeIntermediateState struct {
baseState baseState
} }
@@ -12,11 +14,11 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
} }
switch { switch {
case sliceContains(intermeds, b): case slices.Contains(intermeds, b):
return escState, escState.parser.collectInter() return escState, escState.parser.collectInter()
case sliceContains(executors, b): case slices.Contains(executors, b):
return escState, escState.parser.execute() return escState, escState.parser.execute()
case sliceContains(escapeIntermediateToGroundBytes, b): case slices.Contains(escapeIntermediateToGroundBytes, b):
return escState.parser.ground, nil return escState.parser.ground, nil
} }
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type escapeState struct { type escapeState struct {
baseState baseState
} }
@@ -16,11 +18,11 @@ func (escState escapeState) Handle(b byte) (s state, e error) {
return escState.parser.csiEntry, nil return escState.parser.csiEntry, nil
case b == ANSI_OSC_STRING_ENTRY: case b == ANSI_OSC_STRING_ENTRY:
return escState.parser.oscString, nil return escState.parser.oscString, nil
case sliceContains(executors, b): case slices.Contains(executors, b):
return escState, escState.parser.execute() return escState, escState.parser.execute()
case sliceContains(escapeToGroundBytes, b): case slices.Contains(escapeToGroundBytes, b):
return escState.parser.ground, nil return escState.parser.ground, nil
case sliceContains(intermeds, b): case slices.Contains(intermeds, b):
return escState.parser.escapeIntermediate, nil return escState.parser.escapeIntermediate, nil
} }
+4 -2
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type groundState struct { type groundState struct {
baseState baseState
} }
@@ -13,10 +15,10 @@ func (gs groundState) Handle(b byte) (s state, e error) {
} }
switch { switch {
case sliceContains(printables, b): case slices.Contains(printables, b):
return gs, gs.parser.print() return gs, gs.parser.print()
case sliceContains(executors, b): case slices.Contains(executors, b):
return gs, gs.parser.execute() return gs, gs.parser.execute()
} }
+4 -4
View File
@@ -20,12 +20,12 @@ type AnsiParser struct {
oscString state oscString state
stateMap []state stateMap []state
logf func(string, ...interface{}) logf func(string, ...any)
} }
type Option func(*AnsiParser) type Option func(*AnsiParser)
func WithLogf(f func(string, ...interface{})) Option { func WithLogf(f func(string, ...any)) Option {
return func(ap *AnsiParser) { return func(ap *AnsiParser) {
ap.logf = f ap.logf = f
} }
@@ -45,7 +45,7 @@ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Opti
logger := log.New(logFile, "", log.LstdFlags) logger := log.New(logFile, "", log.LstdFlags)
if ap.logf != nil { if ap.logf != nil {
l := ap.logf l := ap.logf
ap.logf = func(s string, v ...interface{}) { ap.logf = func(s string, v ...any) {
l(s, v...) l(s, v...)
logger.Printf(s, v...) logger.Printf(s, v...)
} }
@@ -55,7 +55,7 @@ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Opti
} }
if ap.logf == nil { if ap.logf == nil {
ap.logf = func(string, ...interface{}) {} ap.logf = func(string, ...any) {}
} }
ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}} ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
+1 -1
View File
@@ -49,7 +49,7 @@ func getInts(params []string, minCount int, dflt int) []int {
if len(ints) < minCount { if len(ints) < minCount {
remaining := minCount - len(ints) remaining := minCount - len(ints)
for i := 0; i < remaining; i++ { for range remaining {
ints = append(ints, dflt) ints = append(ints, dflt)
} }
} }
+4 -2
View File
@@ -1,5 +1,7 @@
package ansiterm package ansiterm
import "slices"
type state interface { type state interface {
Enter() error Enter() error
Exit() error Exit() error
@@ -32,7 +34,7 @@ func (base baseState) Handle(b byte) (s state, e error) {
return base.parser.escape, nil return base.parser.escape, nil
case b == OSC_STRING: case b == OSC_STRING:
return base.parser.oscString, nil return base.parser.oscString, nil
case sliceContains(toGroundBytes, b): case slices.Contains(toGroundBytes, b):
return base.parser.ground, nil return base.parser.ground, nil
} }
@@ -52,7 +54,7 @@ func (base baseState) Transition(s state) error {
execBytes = append(execBytes, 0x99) execBytes = append(execBytes, 0x99)
execBytes = append(execBytes, 0x9A) execBytes = append(execBytes, 0x9A)
if sliceContains(execBytes, base.parser.context.currentChar) { if slices.Contains(execBytes, base.parser.context.currentChar) {
return base.parser.execute() return base.parser.execute()
} }
} }
-11
View File
@@ -1,11 +0,0 @@
package ansiterm
func sliceContains(bytes []byte, b byte) bool {
for _, v := range bytes {
if v == b {
return true
}
}
return false
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
+96 -90
View File
@@ -1,14 +1,17 @@
// +build windows //go:build windows
package winterm package winterm
import ( import (
"fmt" "fmt"
"runtime"
"syscall" "syscall"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
) )
//=========================================================================================================== // ===========================================================================================================
// IMPORTANT NOTE: // IMPORTANT NOTE:
// //
// The methods below make extensive use of the "unsafe" package to obtain the required pointers. // The methods below make extensive use of the "unsafe" package to obtain the required pointers.
@@ -26,51 +29,50 @@ import (
// -- The value is not referenced by the method after passing the pointer to Windows // -- The value is not referenced by the method after passing the pointer to Windows
// //
// See http://golang.org/doc/go1.3. // See http://golang.org/doc/go1.3.
//=========================================================================================================== // ===========================================================================================================
var ( var (
kernel32DLL = syscall.NewLazyDLL("kernel32.dll") kernel32DLL = windows.NewLazyDLL("kernel32.dll")
getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo") getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo")
setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo") setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo")
setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition")
setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize") setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA") scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA")
setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo") setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo")
writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW") writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW")
readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW") readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW")
waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject")
) )
// Windows Console constants // Console modes
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
const ( const (
// Console modes ENABLE_PROCESSED_INPUT = windows.ENABLE_PROCESSED_INPUT
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. ENABLE_LINE_INPUT = windows.ENABLE_LINE_INPUT
ENABLE_PROCESSED_INPUT = 0x0001 ENABLE_ECHO_INPUT = windows.ENABLE_ECHO_INPUT
ENABLE_LINE_INPUT = 0x0002 ENABLE_WINDOW_INPUT = windows.ENABLE_WINDOW_INPUT
ENABLE_ECHO_INPUT = 0x0004 ENABLE_MOUSE_INPUT = windows.ENABLE_MOUSE_INPUT
ENABLE_WINDOW_INPUT = 0x0008 ENABLE_INSERT_MODE = windows.ENABLE_INSERT_MODE
ENABLE_MOUSE_INPUT = 0x0010 ENABLE_QUICK_EDIT_MODE = windows.ENABLE_QUICK_EDIT_MODE
ENABLE_INSERT_MODE = 0x0020 ENABLE_EXTENDED_FLAGS = windows.ENABLE_EXTENDED_FLAGS
ENABLE_QUICK_EDIT_MODE = 0x0040 ENABLE_AUTO_POSITION = windows.ENABLE_AUTO_POSITION
ENABLE_EXTENDED_FLAGS = 0x0080 ENABLE_VIRTUAL_TERMINAL_INPUT = windows.ENABLE_VIRTUAL_TERMINAL_INPUT
ENABLE_AUTO_POSITION = 0x0100
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
ENABLE_PROCESSED_OUTPUT = 0x0001 ENABLE_PROCESSED_OUTPUT = windows.ENABLE_PROCESSED_OUTPUT
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 ENABLE_WRAP_AT_EOL_OUTPUT = windows.ENABLE_WRAP_AT_EOL_OUTPUT
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 ENABLE_VIRTUAL_TERMINAL_PROCESSING = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
DISABLE_NEWLINE_AUTO_RETURN = 0x0008 DISABLE_NEWLINE_AUTO_RETURN = windows.DISABLE_NEWLINE_AUTO_RETURN
ENABLE_LVB_GRID_WORLDWIDE = 0x0010 ENABLE_LVB_GRID_WORLDWIDE = windows.ENABLE_LVB_GRID_WORLDWIDE
)
// Character attributes // Character attributes
// Note: //
// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). // Foreground and background attributes can be combined to produce colors.
// Clearing all foreground or background colors results in black; setting all creates white. // Clearing all foreground or background color bits produces black; setting
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. // all color bits produces white.
//
// See https://learn.microsoft.com/windows/console/char-info-str.
const (
FOREGROUND_BLUE uint16 = 0x0001 FOREGROUND_BLUE uint16 = 0x0001
FOREGROUND_GREEN uint16 = 0x0002 FOREGROUND_GREEN uint16 = 0x0002
FOREGROUND_RED uint16 = 0x0004 FOREGROUND_RED uint16 = 0x0004
@@ -86,23 +88,29 @@ const (
COMMON_LVB_MASK uint16 = 0xFF00 COMMON_LVB_MASK uint16 = 0xFF00
COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000 COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000
COMMON_LVB_UNDERSCORE uint16 = 0x8000 COMMON_LVB_UNDERSCORE uint16 = 0x8000
)
// Input event types // Input event types
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
KEY_EVENT = 0x0001 const (
MOUSE_EVENT = 0x0002 KEY_EVENT = windows.KEY_EVENT
WINDOW_BUFFER_SIZE_EVENT = 0x0004 MOUSE_EVENT = windows.MOUSE_EVENT
MENU_EVENT = 0x0008 WINDOW_BUFFER_SIZE_EVENT = windows.WINDOW_BUFFER_SIZE_EVENT
FOCUS_EVENT = 0x0010 MENU_EVENT = windows.MENU_EVENT
FOCUS_EVENT = windows.FOCUS_EVENT
)
// WaitForSingleObject return codes // WaitForSingleObject return codes.
WAIT_ABANDONED = 0x00000080 const (
WAIT_FAILED = 0xFFFFFFFF WAIT_ABANDONED = windows.WAIT_ABANDONED
WAIT_SIGNALED = 0x0000000 WAIT_FAILED = windows.WAIT_FAILED
WAIT_TIMEOUT = 0x00000102 WAIT_SIGNALED = windows.WAIT_OBJECT_0
WAIT_TIMEOUT = 0x00000102 // Keep as untyped int for backward compat; windows.WAIT_TIMEOUT is typed as syscall.Errno.
)
// WaitForSingleObject wait duration // WaitForSingleObject wait durations.
WAIT_INFINITE = 0xFFFFFFFF const (
WAIT_INFINITE = windows.INFINITE
WAIT_ONE_SECOND = 1000 WAIT_ONE_SECOND = 1000
WAIT_HALF_SECOND = 500 WAIT_HALF_SECOND = 500
WAIT_QUARTER_SECOND = 250 WAIT_QUARTER_SECOND = 250
@@ -122,6 +130,8 @@ type (
Visible int32 Visible int32
} }
// CONSOLE_SCREEN_BUFFER_INFO is identical to [windows.ConsoleScreenBufferInfo]
// but implements [fmt.Stringer].
CONSOLE_SCREEN_BUFFER_INFO struct { CONSOLE_SCREEN_BUFFER_INFO struct {
Size COORD Size COORD
CursorPosition COORD CursorPosition COORD
@@ -130,17 +140,11 @@ type (
MaximumWindowSize COORD MaximumWindowSize COORD
} }
COORD struct { // COORD is identical to [windows.Coord] but implements [fmt.Stringer].
X int16 COORD windows.Coord
Y int16
}
SMALL_RECT struct { // SMALL_RECT is identical to [windows.SmallRect] but implements [fmt.Stringer].
Left int16 SMALL_RECT windows.SmallRect
Top int16
Right int16
Bottom int16
}
// INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest // INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
@@ -189,43 +193,45 @@ func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error
// SetConsoleCursorPosition location of the console cursor. // SetConsoleCursorPosition location of the console cursor.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx.
func SetConsoleCursorPosition(handle uintptr, coord COORD) error { func SetConsoleCursorPosition(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord)) return windows.SetConsoleCursorPosition(windows.Handle(handle), windows.Coord(coord))
use(coord)
return checkError(r1, r2, err)
} }
// GetConsoleMode gets the console mode for given file descriptor // GetConsoleMode gets the console mode for the given handle.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx. // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx.
func GetConsoleMode(handle uintptr) (mode uint32, err error) { func GetConsoleMode(handle uintptr) (mode uint32, err error) {
err = syscall.GetConsoleMode(syscall.Handle(handle), &mode) err = windows.GetConsoleMode(windows.Handle(handle), &mode)
return mode, err return mode, err
} }
// SetConsoleMode sets the console mode for given file descriptor // SetConsoleMode sets the console mode for the given handle.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
func SetConsoleMode(handle uintptr, mode uint32) error { func SetConsoleMode(handle uintptr, mode uint32) error {
r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0) return windows.SetConsoleMode(windows.Handle(handle), mode)
use(mode)
return checkError(r1, r2, err)
} }
// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer. // GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx. // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx.
func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) { func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
info := CONSOLE_SCREEN_BUFFER_INFO{} var info windows.ConsoleScreenBufferInfo
err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)) if err := windows.GetConsoleScreenBufferInfo(windows.Handle(handle), &info); err != nil {
if err != nil {
return nil, err return nil, err
} }
return &info, nil
return &CONSOLE_SCREEN_BUFFER_INFO{
Size: COORD(info.Size),
CursorPosition: COORD(info.CursorPosition),
Attributes: info.Attributes,
Window: SMALL_RECT(info.Window),
MaximumWindowSize: COORD(info.MaximumWindowSize),
}, nil
} }
func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error { func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error {
r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char))) r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char)))
use(scrollRect) runtime.KeepAlive(scrollRect)
use(clipRect) runtime.KeepAlive(clipRect)
use(destOrigin) runtime.KeepAlive(destOrigin)
use(char) runtime.KeepAlive(char)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -233,7 +239,7 @@ func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect S
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx.
func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error { func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord)) r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord))
use(coord) runtime.KeepAlive(coord)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -242,7 +248,7 @@ func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx.
func SetConsoleTextAttribute(handle uintptr, attribute uint16) error { func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0) r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
use(attribute) runtime.KeepAlive(attribute)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -251,8 +257,8 @@ func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx.
func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error { func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error {
r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect))) r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect)))
use(isAbsolute) runtime.KeepAlive(isAbsolute)
use(rect) runtime.KeepAlive(rect)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -260,9 +266,9 @@ func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) erro
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx.
func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error { func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error {
r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion))) r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))
use(buffer) runtime.KeepAlive(buffer)
use(bufferSize) runtime.KeepAlive(bufferSize)
use(bufferCoord) runtime.KeepAlive(bufferCoord)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -270,7 +276,7 @@ func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bu
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx.
func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error { func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error {
r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count))) r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count)))
use(buffer) runtime.KeepAlive(buffer)
return checkError(r1, r2, err) return checkError(r1, r2, err)
} }
@@ -278,15 +284,19 @@ func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) erro
// It returns true if the handle was signaled; false otherwise. // It returns true if the handle was signaled; false otherwise.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx.
func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) { func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) {
r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait))) event, err := windows.WaitForSingleObject(windows.Handle(handle), msWait)
switch r1 { if err != nil {
case WAIT_ABANDONED, WAIT_TIMEOUT: return false, err
}
switch event {
case windows.WAIT_ABANDONED, uint32(windows.WAIT_TIMEOUT):
return false, nil return false, nil
case WAIT_SIGNALED: case windows.WAIT_OBJECT_0:
return true, nil return true, nil
default:
return false, nil
} }
use(msWait)
return false, err
} }
// String helpers // String helpers
@@ -321,7 +331,3 @@ func coordToPointer(c COORD) uintptr {
// Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass. // Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass.
return uintptr(*((*uint32)(unsafe.Pointer(&c)))) return uintptr(*((*uint32)(unsafe.Pointer(&c))))
} }
// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
func use(p interface{}) {}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
+11 -33
View File
@@ -1,10 +1,12 @@
// +build windows //go:build windows
package winterm package winterm
const ( const (
horizontal = iota horizontal = iota
vertical vertical
line
column
) )
func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT { func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT {
@@ -58,44 +60,20 @@ func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error {
position.X += int16(param) position.X += int16(param)
case vertical: case vertical:
position.Y += int16(param) position.Y += int16(param)
case line:
position.X = 0
position.Y += int16(param)
case column:
position.X = int16(param) - 1
} }
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { return h.setCursorPosition(position, h.getCursorWindow(info))
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) moveCursorLine(param int) error { func (h *windowsAnsiEventHandler) moveCursorLine(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd) return h.moveCursor(line, param)
if err != nil {
return err
}
position := info.CursorPosition
position.X = 0
position.Y += int16(param)
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error { func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd) return h.moveCursor(column, param)
if err != nil {
return err
}
position := info.CursorPosition
position.X = int16(param) - 1
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
} }
+3 -13
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
@@ -50,12 +50,7 @@ func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD,
coordStart.X, coordStart.Y = xCurrent, yCurrent coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yEnd coordEnd.X, coordEnd.Y = xEnd, yEnd
err = h.clearRect(attributes, coordStart, coordEnd) return h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error { func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error {
@@ -75,10 +70,5 @@ func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD,
buffer[i] = char buffer[i] = char
} }
err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region) return WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
if err != nil {
return err
}
return nil
} }
+4 -11
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
@@ -39,9 +39,8 @@ func (h *windowsAnsiEventHandler) deleteLines(param int) error {
if start >= sr.top && start <= sr.bottom { if start >= sr.top && start <= sr.bottom {
sr.top = start sr.top = start
return h.scroll(param, sr, info) return h.scroll(param, sr, info)
} else {
return nil
} }
return nil
} }
func (h *windowsAnsiEventHandler) insertLines(param int) error { func (h *windowsAnsiEventHandler) insertLines(param int) error {
@@ -72,10 +71,7 @@ func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSO
Attributes: h.attributes, Attributes: h.attributes,
} }
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { func (h *windowsAnsiEventHandler) deleteCharacters(param int) error {
@@ -111,8 +107,5 @@ func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *
Attributes: h.attributes, Attributes: h.attributes,
} }
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
return err
}
return nil
} }
+1 -1
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
+19 -33
View File
@@ -1,4 +1,4 @@
// +build windows //go:build windows
package winterm package winterm
@@ -169,9 +169,7 @@ func (h *windowsAnsiEventHandler) executeLF() error {
return err return err
} }
h.logf("Resetting cursor position for LF without CR") h.logf("Resetting cursor position for LF without CR")
if err := SetConsoleCursorPosition(h.fd, pos); err != nil { return SetConsoleCursorPosition(h.fd, pos)
return err
}
} }
} }
return nil return nil
@@ -373,7 +371,7 @@ func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
} }
window := h.getCursorWindow(info) window := h.getCursorWindow(info)
position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1} position := COORD{X: window.Left + int16(col) - 1, Y: window.Top + int16(row) - 1}
return h.setCursorPosition(position, window) return h.setCursorPosition(position, window)
} }
@@ -423,7 +421,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
targetWidth = 132 targetWidth = 132
} }
if info.Size.X < targetWidth { if info.Size.X < targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { if err := SetConsoleScreenBufferSize(h.fd, COORD{X: targetWidth, Y: info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err) h.logf("set buffer failed: %v", err)
return err return err
} }
@@ -436,12 +434,12 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
return err return err
} }
if info.Size.X > targetWidth { if info.Size.X > targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { if err := SetConsoleScreenBufferSize(h.fd, COORD{X: targetWidth, Y: info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err) h.logf("set buffer failed: %v", err)
return err return err
} }
} }
return SetConsoleCursorPosition(h.fd, COORD{0, 0}) return SetConsoleCursorPosition(h.fd, COORD{X: 0, Y: 0})
} }
func (h *windowsAnsiEventHandler) ED(param int) error { func (h *windowsAnsiEventHandler) ED(param int) error {
@@ -468,15 +466,15 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
switch param { switch param {
case 0: case 0:
start = info.CursorPosition start = info.CursorPosition
end = COORD{info.Size.X - 1, info.Size.Y - 1} end = COORD{X: info.Size.X - 1, Y: info.Size.Y - 1}
case 1: case 1:
start = COORD{0, 0} start = COORD{X: 0, Y: 0}
end = info.CursorPosition end = info.CursorPosition
case 2: case 2:
start = COORD{0, 0} start = COORD{X: 0, Y: 0}
end = COORD{info.Size.X - 1, info.Size.Y - 1} end = COORD{X: info.Size.X - 1, Y: info.Size.Y - 1}
} }
err = h.clearRange(h.attributes, start, end) err = h.clearRange(h.attributes, start, end)
@@ -495,9 +493,7 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
if err := SetConsoleCursorPosition(h.fd, pos); err != nil { if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err return err
} }
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { return SetConsoleWindowInfo(h.fd, true, window)
return err
}
} }
return nil return nil
@@ -525,23 +521,18 @@ func (h *windowsAnsiEventHandler) EL(param int) error {
switch param { switch param {
case 0: case 0:
start = info.CursorPosition start = info.CursorPosition
end = COORD{info.Size.X, info.CursorPosition.Y} end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
case 1: case 1:
start = COORD{0, info.CursorPosition.Y} start = COORD{X: 0, Y: info.CursorPosition.Y}
end = info.CursorPosition end = info.CursorPosition
case 2: case 2:
start = COORD{0, info.CursorPosition.Y} start = COORD{X: 0, Y: info.CursorPosition.Y}
end = COORD{info.Size.X, info.CursorPosition.Y} end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
} }
err = h.clearRange(h.attributes, start, end) return h.clearRange(h.attributes, start, end)
if err != nil {
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) IL(param int) error { func (h *windowsAnsiEventHandler) IL(param int) error {
@@ -611,12 +602,7 @@ func (h *windowsAnsiEventHandler) SGR(params []int) error {
if h.inverted { if h.inverted {
attributes = invertAttributes(attributes) attributes = invertAttributes(attributes)
} }
err := SetConsoleTextAttribute(h.fd, attributes) return SetConsoleTextAttribute(h.fd, attributes)
if err != nil {
return err
}
return nil
} }
func (h *windowsAnsiEventHandler) SU(param int) error { func (h *windowsAnsiEventHandler) SU(param int) error {
@@ -702,8 +688,8 @@ func (h *windowsAnsiEventHandler) Flush() error {
} }
charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}} charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}}
size := COORD{1, 1} size := COORD{X: 1, Y: 1}
position := COORD{0, 0} position := COORD{X: 0, Y: 0}
region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y} region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y}
if err := WriteConsoleOutput(h.fd, charInfo, size, position, &region); err != nil { if err := WriteConsoleOutput(h.fd, charInfo, size, position, &region); err != nil {
return err return err
+33 -3
View File
@@ -408,7 +408,10 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
(*obj.protected)[k] = makeRawMessage(b) (*obj.protected)[k] = makeRawMessage(b)
} }
authData := obj.computeAuthData() authData, err := obj.computeAuthData()
if err != nil {
return nil, err
}
parts, err := ctx.cipher.encrypt(cek, authData, plaintext) parts, err := ctx.cipher.encrypt(cek, authData, plaintext)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -428,6 +431,13 @@ func (ctx *genericEncrypter) Options() EncrypterOptions {
} }
} }
func validateContentEncryptionKeySize(cek []byte, cipher contentCipher) error {
if len(cek) != cipher.keySize() {
return ErrInvalidKeySize
}
return nil
}
// Decrypt and validate the object and return the plaintext. This // Decrypt and validate the object and return the plaintext. This
// function does not support multi-recipient. If you desire multi-recipient // function does not support multi-recipient. If you desire multi-recipient
// decryption use DecryptMulti instead. // decryption use DecryptMulti instead.
@@ -485,7 +495,10 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
tag: obj.tag, tag: obj.tag,
} }
authData := obj.computeAuthData() authData, err := obj.computeAuthData()
if err != nil {
return nil, err
}
var plaintext []byte var plaintext []byte
recipient := obj.recipients[0] recipient := obj.recipients[0]
@@ -495,6 +508,10 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
if err != nil { if err != nil {
return nil, ErrCryptoFailure return nil, ErrCryptoFailure
} }
err = validateContentEncryptionKeySize(cek, cipher)
if err != nil {
return nil, ErrCryptoFailure
}
// Found a valid CEK -- let's try to decrypt. // Found a valid CEK -- let's try to decrypt.
plaintext, err = cipher.decrypt(cek, authData, parts) plaintext, err = cipher.decrypt(cek, authData, parts)
@@ -520,6 +537,12 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
// //
// Automatically decompresses plaintext, but returns an error if the decompressed // Automatically decompresses plaintext, but returns an error if the decompressed
// data would be >250kB or >3x the size of the compressed data, whichever is larger. // data would be >250kB or >3x the size of the compressed data, whichever is larger.
//
// Calling DecryptMulti() with PBES2 enabled can result in excessive CPU work.
// The PBES2 key unwrapping algorithms are intentionally expensive, and have to
// be run for each recipient. To be safe: don't allow PBES2 algorithms in calls
// to ParseEncrypted / ParseEncryptedJSON. If your application requires PBES2,
// prefer Decrypt(), which will only process single-recipient messages.
func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) { func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Header, []byte, error) {
globalHeaders := obj.mergedHeaders(nil) globalHeaders := obj.mergedHeaders(nil)
@@ -553,7 +576,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
tag: obj.tag, tag: obj.tag,
} }
authData := obj.computeAuthData() authData, err := obj.computeAuthData()
if err != nil {
return -1, Header{}, nil, err
}
index := -1 index := -1
var plaintext []byte var plaintext []byte
@@ -572,6 +598,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
if err != nil { if err != nil {
continue continue
} }
err = validateContentEncryptionKeySize(cek, cipher)
if err != nil {
continue
}
// Found a valid CEK -- let's try to decrypt. // Found a valid CEK -- let's try to decrypt.
plaintext, err = cipher.decrypt(cek, authData, parts) plaintext, err = cipher.decrypt(cek, authData, parts)
+6 -32
View File
@@ -30,30 +30,6 @@ import (
"github.com/go-jose/go-jose/v4/json" "github.com/go-jose/go-jose/v4/json"
) )
// Helper function to serialize known-good objects.
// Precondition: value is not a nil pointer.
func mustSerializeJSON(value interface{}) []byte {
out, err := json.Marshal(value)
if err != nil {
panic(err)
}
// We never want to serialize the top-level value "null," since it's not a
// valid JOSE message. But if a caller passes in a nil pointer to this method,
// MarshalJSON will happily serialize it as the top-level value "null". If
// that value is then embedded in another operation, for instance by being
// base64-encoded and fed as input to a signing algorithm
// (https://github.com/go-jose/go-jose/issues/22), the result will be
// incorrect. Because this method is intended for known-good objects, and a nil
// pointer is not a known-good object, we are free to panic in this case.
// Note: It's not possible to directly check whether the data pointed at by an
// interface is a nil pointer, so we do this hacky workaround.
// https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I
if string(out) == "null" {
panic("Tried to serialize a nil pointer.")
}
return out
}
// Strip all newlines and whitespace // Strip all newlines and whitespace
func stripWhitespace(data string) string { func stripWhitespace(data string) string {
buf := strings.Builder{} buf := strings.Builder{}
@@ -122,6 +98,8 @@ func inflate(input []byte) ([]byte, error) {
} }
// byteBuffer represents a slice of bytes that can be serialized to url-safe base64. // byteBuffer represents a slice of bytes that can be serialized to url-safe base64.
//
// A nil byteBuffer represents an empty slice of bytes.
type byteBuffer struct { type byteBuffer struct {
data []byte data []byte
} }
@@ -169,13 +147,13 @@ func (b *byteBuffer) UnmarshalJSON(data []byte) error {
return err return err
} }
*b = *newBuffer(decoded) b.data = decoded
return nil return nil
} }
func (b *byteBuffer) base64() string { func (b *byteBuffer) base64() string {
return base64.RawURLEncoding.EncodeToString(b.data) return base64.RawURLEncoding.EncodeToString(b.bytes())
} }
func (b *byteBuffer) bytes() []byte { func (b *byteBuffer) bytes() []byte {
@@ -186,12 +164,8 @@ func (b *byteBuffer) bytes() []byte {
return b.data return b.data
} }
func (b byteBuffer) bigInt() *big.Int { func (b *byteBuffer) bigInt() *big.Int {
return new(big.Int).SetBytes(b.data) return new(big.Int).SetBytes(b.bytes())
}
func (b byteBuffer) toInt() int {
return int(b.bigInt().Int64())
} }
func base64EncodeLen(sl []byte) int { func base64EncodeLen(sl []byte) int {
+13
View File
@@ -671,6 +671,19 @@ func (d *decodeState) object(v reflect.Value) {
for _, i := range f.index { for _, i := range f.index {
if subv.Kind() == reflect.Ptr { if subv.Kind() == reflect.Ptr {
if subv.IsNil() { if subv.IsNil() {
// If a struct embeds a pointer to an unexported type,
// it is not possible to set a newly allocated value
// since the field is unexported.
//
// See https://golang.org/issue/21357
if !subv.CanSet() {
d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem()))
// Invalidate subv to ensure d.value(subv) skips over
// the JSON value without assigning it to subv.
subv = reflect.Value{}
destring = false
break
}
subv.Set(reflect.New(subv.Type().Elem())) subv.Set(reflect.New(subv.Type().Elem()))
} }
subv = subv.Elem() subv = subv.Elem()
+13 -1
View File
@@ -1025,7 +1025,19 @@ func typeFields(t reflect.Type) []field {
// Scan f.typ for fields to include. // Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ { for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i) sf := f.typ.Field(i)
if sf.PkgPath != "" && !sf.Anonymous { // unexported if sf.Anonymous {
t := sf.Type
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
if !sf.IsExported() && t.Kind() != reflect.Struct {
// Ignore embedded fields of unexported non-struct types.
continue
}
// Do not ignore embedded fields of unexported struct types
// since they may have exported fields.
} else if !sf.IsExported() {
// Ignore unexported non-embedded fields.
continue continue
} }
tag := sf.Tag.Get("json") tag := sf.Tag.Get("json")
+59 -25
View File
@@ -25,6 +25,12 @@ import (
"github.com/go-jose/go-jose/v4/json" "github.com/go-jose/go-jose/v4/json"
) )
// MaxRecipients is the maximum number of recipients of a JWE at parse time.
// Higher values mean more potential work done across untrusted input.
//
// If modifying MaxRecipients, do it before any parsing occurs.
var MaxRecipients = 32
// rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing. // rawJSONWebEncryption represents a raw JWE JSON object. Used for parsing/serializing.
type rawJSONWebEncryption struct { type rawJSONWebEncryption struct {
Protected *byteBuffer `json:"protected,omitempty"` Protected *byteBuffer `json:"protected,omitempty"`
@@ -84,14 +90,18 @@ func (obj JSONWebEncryption) mergedHeaders(recipient *recipientInfo) rawHeader {
} }
// Get the additional authenticated data from a JWE object. // Get the additional authenticated data from a JWE object.
func (obj JSONWebEncryption) computeAuthData() []byte { func (obj JSONWebEncryption) computeAuthData() ([]byte, error) {
var protected string var protected string
switch { switch {
case obj.original != nil && obj.original.Protected != nil: case obj.original != nil && obj.original.Protected != nil:
protected = obj.original.Protected.base64() protected = obj.original.Protected.base64()
case obj.protected != nil: case obj.protected != nil:
protected = base64.RawURLEncoding.EncodeToString(mustSerializeJSON((obj.protected))) serializedProtected, err := json.Marshal(obj.protected)
if err != nil {
return nil, err
}
protected = base64.RawURLEncoding.EncodeToString(serializedProtected)
default: default:
protected = "" protected = ""
} }
@@ -102,7 +112,7 @@ func (obj JSONWebEncryption) computeAuthData() []byte {
output = append(output, []byte(base64.RawURLEncoding.EncodeToString(obj.aad))...) output = append(output, []byte(base64.RawURLEncoding.EncodeToString(obj.aad))...)
} }
return output return output, nil
} }
func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool { func containsKeyAlgorithm(haystack []KeyAlgorithm, needle KeyAlgorithm) bool {
@@ -128,11 +138,10 @@ func containsContentEncryption(haystack []ContentEncryption, needle ContentEncry
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1 // https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2 // https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
// //
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" // The keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in // header parameters respectively. They must be non-empty. Non-matching algorithms cause a parse error.
// parsed data must contain a value that is present in the corresponding parameter. That //
// includes the protected and unprotected headers as well as all recipients. To accept // Deprecated: use ParseEncryptedJSON or ParseEncryptedCompact depending on which serialization you expect.
// multiple algorithms, pass a slice of all the algorithms you want to accept.
func ParseEncrypted(input string, func ParseEncrypted(input string,
keyEncryptionAlgorithms []KeyAlgorithm, keyEncryptionAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption, contentEncryption []ContentEncryption,
@@ -145,9 +154,13 @@ func ParseEncrypted(input string,
return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption) return ParseEncryptedCompact(input, keyEncryptionAlgorithms, contentEncryption)
} }
// ParseEncryptedJSON parses a message in JWE JSON Serialization. // ParseEncryptedJSON parses a message in JWE JSON Serialization. Messages with
// more than [MaxRecipients] recipients are rejected.
// //
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.2 // https://datatracker.ietf.org/doc/html/rfc7516#section-3.2
//
// The keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be non-empty. Any non-allowed algorithms will cause parsing to fail.
func ParseEncryptedJSON( func ParseEncryptedJSON(
input string, input string,
keyEncryptionAlgorithms []KeyAlgorithm, keyEncryptionAlgorithms []KeyAlgorithm,
@@ -177,6 +190,9 @@ func (parsed *rawJSONWebEncryption) sanitized(
if len(contentEncryption) == 0 { if len(contentEncryption) == 0 {
return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided") return nil, errors.New("go-jose/go-jose: no content encryption algorithms provided")
} }
if len(parsed.Recipients) > MaxRecipients {
return nil, fmt.Errorf("go-jose/go-jose: too many recipients in JWE; maximum is %d", MaxRecipients)
}
obj := &JSONWebEncryption{ obj := &JSONWebEncryption{
original: parsed, original: parsed,
@@ -195,21 +211,11 @@ func (parsed *rawJSONWebEncryption) sanitized(
} }
} }
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { protected, err := parseProtectedHeader(parsed.Protected)
err := json.Unmarshal(parsed.Protected.bytes(), &obj.protected)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: invalid protected header: %s, %s", err, parsed.Protected.base64())
}
}
// Note: this must be called _after_ we parse the protected header,
// otherwise fields from the protected header will not get picked up.
var err error
mergedHeaders := obj.mergedHeaders(nil)
obj.Header, err = mergedHeaders.sanitized()
if err != nil { if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %v (%v)", err, mergedHeaders) return nil, err
} }
obj.protected = protected
if len(parsed.Recipients) == 0 { if len(parsed.Recipients) == 0 {
obj.recipients = []recipientInfo{ obj.recipients = []recipientInfo{
@@ -264,6 +270,14 @@ func (parsed *rawJSONWebEncryption) sanitized(
} }
} }
// Note: this must be called _after_ we parse the protected header,
// otherwise fields from the protected header will not get picked up.
mergedHeaders := obj.mergedHeaders(nil)
obj.Header, err = mergedHeaders.sanitized()
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: cannot sanitize merged headers: %w", err)
}
obj.iv = parsed.Iv.bytes() obj.iv = parsed.Iv.bytes()
obj.ciphertext = parsed.Ciphertext.bytes() obj.ciphertext = parsed.Ciphertext.bytes()
obj.tag = parsed.Tag.bytes() obj.tag = parsed.Tag.bytes()
@@ -287,6 +301,9 @@ func validateAlgEnc(headers rawHeader, keyAlgorithms []KeyAlgorithm, contentEncr
// ParseEncryptedCompact parses a message in JWE Compact Serialization. // ParseEncryptedCompact parses a message in JWE Compact Serialization.
// //
// https://datatracker.ietf.org/doc/html/rfc7516#section-3.1 // https://datatracker.ietf.org/doc/html/rfc7516#section-3.1
//
// The keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be non-empty. Any non-allowed algorithms will cause parsing to fail.
func ParseEncryptedCompact( func ParseEncryptedCompact(
input string, input string,
keyAlgorithms []KeyAlgorithm, keyAlgorithms []KeyAlgorithm,
@@ -354,7 +371,10 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
return "", ErrNotSupported return "", ErrNotSupported
} }
serializedProtected := mustSerializeJSON(obj.protected) serializedProtected, err := json.Marshal(obj.protected)
if err != nil {
return "", err
}
return base64JoinWithDots( return base64JoinWithDots(
serializedProtected, serializedProtected,
@@ -366,7 +386,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
} }
// FullSerialize serializes an object using the full JSON serialization format. // FullSerialize serializes an object using the full JSON serialization format.
//
// It returns "" if obj cannot be serialized, for example if it has no recipients.
func (obj JSONWebEncryption) FullSerialize() string { func (obj JSONWebEncryption) FullSerialize() string {
if len(obj.recipients) == 0 {
return ""
}
raw := rawJSONWebEncryption{ raw := rawJSONWebEncryption{
Unprotected: obj.unprotected, Unprotected: obj.unprotected,
Iv: newBuffer(obj.iv), Iv: newBuffer(obj.iv),
@@ -392,8 +418,16 @@ func (obj JSONWebEncryption) FullSerialize() string {
} }
if obj.protected != nil { if obj.protected != nil {
raw.Protected = newBuffer(mustSerializeJSON(obj.protected)) serializedProtected, err := json.Marshal(obj.protected)
if err != nil {
return ""
}
raw.Protected = newBuffer(serializedProtected)
} }
return string(mustSerializeJSON(raw)) out, err := json.Marshal(raw)
if err != nil {
return ""
}
return string(out)
} }
+74 -24
View File
@@ -30,6 +30,7 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"net/url" "net/url"
"reflect" "reflect"
@@ -177,13 +178,29 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
// UnmarshalJSON reads a key from its JSON representation. // UnmarshalJSON reads a key from its JSON representation.
// //
// Returns ErrUnsupportedKeyType for unrecognized or unsupported "kty" header values. // Returns ErrUnsupportedKeyType for unrecognized or unsupported "kty" header values.
func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) { //
// Directly unmarshaling a JWK is not safe for untrusted input.
func (k *JSONWebKey) UnmarshalJSON(data []byte) error {
return k.unmarshalJSON(data, true)
}
// unmarshalJSON reads a key from its JSON representation.
//
// If allowPrivate is false, a JWK with private key material is rejected and the
// function is safe for use against untrusted input.
func (k *JSONWebKey) unmarshalJSON(data []byte, allowPrivate bool) (err error) {
var raw rawJSONWebKey var raw rawJSONWebKey
err = json.Unmarshal(data, &raw) err = json.Unmarshal(data, &raw)
if err != nil { if err != nil {
return err return err
} }
if !allowPrivate &&
(raw.K != nil || raw.D != nil || raw.P != nil || raw.Q != nil ||
raw.Dp != nil || raw.Dq != nil || raw.Qi != nil) {
return errors.New("go-jose/go-jose: JWK contains private parameters")
}
certs, err := parseCertificateChain(raw.X5c) certs, err := parseCertificateChain(raw.X5c)
if err != nil { if err != nil {
return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err) return fmt.Errorf("go-jose/go-jose: failed to unmarshal x5c field: %s", err)
@@ -233,7 +250,7 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
keyPub = key keyPub = key
} }
case "oct": case "oct":
if certPub != nil { if len(certs) > 0 {
return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain") return errors.New("go-jose/go-jose: invalid JWK, found 'oct' (symmetric) key with cert chain")
} }
key, err = raw.symmetricKey() key, err = raw.symmetricKey()
@@ -272,10 +289,8 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
return ErrUnsupportedKeyType return ErrUnsupportedKeyType
} }
if certPub != nil && keyPub != nil { if len(certs) > 0 && (certPub == nil || !reflect.DeepEqual(certPub, keyPub)) {
if !reflect.DeepEqual(certPub, keyPub) { return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
}
} }
*k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs} *k = JSONWebKey{Key: key, KeyID: raw.Kid, Algorithm: raw.Alg, Use: raw.Use, Certificates: certs}
@@ -392,6 +407,9 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.Int) (string, error) {
} }
func rsaThumbprintInput(n *big.Int, e int) (string, error) { func rsaThumbprintInput(n *big.Int, e int) (string, error) {
if n == nil || e <= 0 {
return "", errors.New("go-jose/go-jose: invalid RSA key")
}
return fmt.Sprintf(rsaThumbprintTemplate, return fmt.Sprintf(rsaThumbprintTemplate,
newBufferFromInt(uint64(e)).base64(), newBufferFromInt(uint64(e)).base64(),
newBuffer(n.Bytes()).base64()), nil newBuffer(n.Bytes()).base64()), nil
@@ -505,14 +523,41 @@ func (k *JSONWebKey) Valid() bool {
return true return true
} }
// MaxRSAModulusBits is the largest RSA modulus size, in bits, that will be
// accepted when parsing a JWK or verifying an x5c certificate chain with
// [Header.Certificates]. Applications that need larger keys can raise this
// limit.
//
// If modifying MaxRSAModulusBits, do it before any parsing occurs.
var MaxRSAModulusBits = 4096
func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) { func (key rawJSONWebKey) rsaPublicKey() (*rsa.PublicKey, error) {
if key.N == nil || key.E == nil { return rsaPublicKey(key.N, key.E)
}
func rsaPublicKey(N, E *byteBuffer) (*rsa.PublicKey, error) {
if N == nil || E == nil {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values") return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, missing n/e values")
} }
n := N.bigInt()
if n.BitLen() > MaxRSAModulusBits {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, modulus too large")
}
e := new(big.Int).SetBytes(E.bytes())
if !e.IsInt64() {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, bad e value")
}
eInt64 := e.Int64()
if eInt64 < 2 || eInt64 > math.MaxInt {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key, bad e value")
}
return &rsa.PublicKey{ return &rsa.PublicKey{
N: key.N.bigInt(), N: n,
E: key.E.toInt(), E: int(eInt64),
}, nil }, nil
} }
@@ -556,11 +601,11 @@ func (key rawJSONWebKey) ecPublicKey() (*ecdsa.PublicKey, error) {
// The length of this octet string MUST be the full size of a coordinate for // The length of this octet string MUST be the full size of a coordinate for
// the curve specified in the "crv" parameter. // the curve specified in the "crv" parameter.
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2 // https://tools.ietf.org/html/rfc7518#section-6.2.1.2
if curveSize(curve) != len(key.X.data) { if curveSize(curve) != len(key.X.bytes()) {
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x") return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for x")
} }
if curveSize(curve) != len(key.Y.data) { if curveSize(curve) != len(key.Y.bytes()) {
return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y") return nil, fmt.Errorf("go-jose/go-jose: invalid EC public key, wrong length for y")
} }
@@ -673,16 +718,21 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", ")) return nil, fmt.Errorf("go-jose/go-jose: invalid RSA private key, missing %s value(s)", strings.Join(missing, ", "))
} }
pubKey, err := rsaPublicKey(key.N, key.E)
if err != nil {
return nil, err
}
n := pubKey.N
p, q := key.P.bigInt(), key.Q.bigInt()
if p.BitLen()+q.BitLen() > n.BitLen()+1 || new(big.Int).Mul(p, q).Cmp(n) != 0 {
return nil, errors.New("go-jose/go-jose: invalid RSA private key, p * q != n")
}
rv := &rsa.PrivateKey{ rv := &rsa.PrivateKey{
PublicKey: rsa.PublicKey{ PublicKey: *pubKey,
N: key.N.bigInt(), D: key.D.bigInt(),
E: key.E.toInt(), Primes: []*big.Int{p, q},
},
D: key.D.bigInt(),
Primes: []*big.Int{
key.P.bigInt(),
key.Q.bigInt(),
},
} }
if key.Dp != nil { if key.Dp != nil {
@@ -695,7 +745,7 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
rv.Precomputed.Qinv = key.Qi.bigInt() rv.Precomputed.Qinv = key.Qi.bigInt()
} }
err := rv.Validate() err = rv.Validate()
return rv, err return rv, err
} }
@@ -769,16 +819,16 @@ func (key rawJSONWebKey) ecPrivateKey() (*ecdsa.PrivateKey, error) {
// The length of this octet string MUST be the full size of a coordinate for // The length of this octet string MUST be the full size of a coordinate for
// the curve specified in the "crv" parameter. // the curve specified in the "crv" parameter.
// https://tools.ietf.org/html/rfc7518#section-6.2.1.2 // https://tools.ietf.org/html/rfc7518#section-6.2.1.2
if curveSize(curve) != len(key.X.data) { if curveSize(curve) != len(key.X.bytes()) {
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x") return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for x")
} }
if curveSize(curve) != len(key.Y.data) { if curveSize(curve) != len(key.Y.bytes()) {
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y") return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for y")
} }
// https://tools.ietf.org/html/rfc7518#section-6.2.2.1 // https://tools.ietf.org/html/rfc7518#section-6.2.2.1
if dSize(curve) != len(key.D.data) { if dSize(curve) != len(key.D.bytes()) {
return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d") return nil, fmt.Errorf("go-jose/go-jose: invalid EC private key, wrong length for d")
} }
+79 -32
View File
@@ -27,6 +27,12 @@ import (
"github.com/go-jose/go-jose/v4/json" "github.com/go-jose/go-jose/v4/json"
) )
// MaxSignatures is the maximum number of signatures in a JWS at parse time.
// Higher values mean more potential work done across untrusted input.
//
// If modifying MaxSignatures, do it before any parsing occurs.
var MaxSignatures = 32
// rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing. // rawJSONWebSignature represents a raw JWS JSON object. Used for parsing/serializing.
type rawJSONWebSignature struct { type rawJSONWebSignature struct {
Payload *byteBuffer `json:"payload,omitempty"` Payload *byteBuffer `json:"payload,omitempty"`
@@ -86,6 +92,11 @@ type Signature struct {
// Verify() after parsing to validate the signature and obtain the payload. // Verify() after parsing to validate the signature and obtain the payload.
// //
// https://datatracker.ietf.org/doc/html/rfc7515#section-7 // https://datatracker.ietf.org/doc/html/rfc7515#section-7
//
// The signatureAlgorithms parameter contains the allowable algorithms in the "alg" header parameter.
// It must be non-empty. Non-matching algorithms cause a parse error.
//
// Deprecated: call ParseSignedJSON or ParseSignedCompact depending on which serialization you expect.
func ParseSigned( func ParseSigned(
signature string, signature string,
signatureAlgorithms []SignatureAlgorithm, signatureAlgorithms []SignatureAlgorithm,
@@ -108,6 +119,9 @@ func ParseSigned(
// Verify() after parsing to validate the signature and obtain the payload. // Verify() after parsing to validate the signature and obtain the payload.
// //
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.1 // https://datatracker.ietf.org/doc/html/rfc7515#section-7.1
//
// The signatureAlgorithms parameter contains the allowable algorithms in the "alg" header parameter.
// It must be non-empty. Non-matching algorithms cause a parse error.
func ParseSignedCompact( func ParseSignedCompact(
signature string, signature string,
signatureAlgorithms []SignatureAlgorithm, signatureAlgorithms []SignatureAlgorithm,
@@ -125,6 +139,9 @@ func ParseSignedCompact(
// parsing. Call Verify() after parsing to validate the signature and obtain the payload. // parsing. Call Verify() after parsing to validate the signature and obtain the payload.
// //
// https://datatracker.ietf.org/doc/html/rfc7515#appendix-F // https://datatracker.ietf.org/doc/html/rfc7515#appendix-F
//
// The signatureAlgorithms parameter contains the allowable algorithms in the "alg" header parameter.
// It must be non-empty. Any non-allowed algorithms will cause parsing to fail.
func ParseDetached( func ParseDetached(
signature string, signature string,
payload []byte, payload []byte,
@@ -157,7 +174,11 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
authData.WriteString(signature.original.Protected.base64()) authData.WriteString(signature.original.Protected.base64())
} else if signature.protected != nil { } else if signature.protected != nil {
protectedHeader = signature.protected protectedHeader = signature.protected
authData.WriteString(base64.RawURLEncoding.EncodeToString(mustSerializeJSON(protectedHeader))) serializedProtected, err := json.Marshal(protectedHeader)
if err != nil {
return nil, err
}
authData.WriteString(base64.RawURLEncoding.EncodeToString(serializedProtected))
} }
needsBase64 := true needsBase64 := true
@@ -180,9 +201,13 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
return authData.Bytes(), nil return authData.Bytes(), nil
} }
// ParseSignedJSON parses a message in JWS JSON Serialization. // ParseSignedJSON parses a message in JWS JSON Serialization. Messages with
// more than [MaxSignatures] signatures are rejected.
// //
// https://datatracker.ietf.org/doc/html/rfc7515#section-7.2 // https://datatracker.ietf.org/doc/html/rfc7515#section-7.2
//
// The signatureAlgorithms parameter contains the allowable algorithms in the "alg" header parameter.
// It must be non-empty. Non-matching algorithms cause a parse error.
func ParseSignedJSON( func ParseSignedJSON(
input string, input string,
signatureAlgorithms []SignatureAlgorithm, signatureAlgorithms []SignatureAlgorithm,
@@ -236,6 +261,9 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
if parsed.Payload == nil { if parsed.Payload == nil {
return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message") return nil, fmt.Errorf("go-jose/go-jose: missing payload in JWS message")
} }
if len(parsed.Signatures) > MaxSignatures {
return nil, fmt.Errorf("go-jose/go-jose: too many signatures in JWS; maximum is %d", MaxSignatures)
}
obj := &JSONWebSignature{ obj := &JSONWebSignature{
payload: parsed.Payload.bytes(), payload: parsed.Payload.bytes(),
@@ -245,14 +273,13 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
if len(parsed.Signatures) == 0 { if len(parsed.Signatures) == 0 {
// No signatures array, must be flattened serialization // No signatures array, must be flattened serialization
signature := Signature{} signature := Signature{}
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 { prot, err := parseProtectedHeader(parsed.Protected)
signature.protected = &rawHeader{} if err != nil {
err := json.Unmarshal(parsed.Protected.bytes(), signature.protected) return nil, err
if err != nil {
return nil, err
}
} }
signature.protected = prot
// Check that there is not a nonce in the unprotected header // Check that there is not a nonce in the unprotected header
if parsed.Header != nil && parsed.Header.getNonce() != "" { if parsed.Header != nil && parsed.Header.getNonce() != "" {
return nil, ErrUnprotectedNonce return nil, ErrUnprotectedNonce
@@ -275,17 +302,17 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
Signature: parsed.Signature, Signature: parsed.Signature,
} }
var err error mergedHeaders := signature.mergedHeaders()
signature.Header, err = signature.mergedHeaders().sanitized() alg := mergedHeaders.getSignatureAlgorithm()
if err != nil {
return nil, err
}
alg := SignatureAlgorithm(signature.Header.Algorithm)
if !containsSignatureAlgorithm(signatureAlgorithms, alg) { if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms) return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
} }
signature.Header, err = mergedHeaders.sanitized()
if err != nil {
return nil, err
}
if signature.header != nil { if signature.header != nil {
signature.Unprotected, err = signature.header.sanitized() signature.Unprotected, err = signature.header.sanitized()
if err != nil { if err != nil {
@@ -310,30 +337,31 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
} }
for i, sig := range parsed.Signatures { for i, sig := range parsed.Signatures {
if sig.Protected != nil && len(sig.Protected.bytes()) > 0 { prot, err := parseProtectedHeader(sig.Protected)
obj.Signatures[i].protected = &rawHeader{} if err != nil {
err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected) return nil, err
if err != nil {
return nil, err
}
} }
obj.Signatures[i].protected = prot
// Check that there is not a nonce in the unprotected header // Check that there is not a nonce in the unprotected header
if sig.Header != nil && sig.Header.getNonce() != "" { if sig.Header != nil && sig.Header.getNonce() != "" {
return nil, ErrUnprotectedNonce return nil, ErrUnprotectedNonce
} }
var err error obj.Signatures[i].header = sig.Header
obj.Signatures[i].Header, err = obj.Signatures[i].mergedHeaders().sanitized()
if err != nil {
return nil, err
}
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm) mergedHeaders := obj.Signatures[i].mergedHeaders()
alg := mergedHeaders.getSignatureAlgorithm()
if !containsSignatureAlgorithm(signatureAlgorithms, alg) { if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms) return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
} }
obj.Signatures[i].Header, err = mergedHeaders.sanitized()
if err != nil {
return nil, err
}
if obj.Signatures[i].header != nil { if obj.Signatures[i].header != nil {
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized() obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
if err != nil { if err != nil {
@@ -359,7 +387,6 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
// Copy value of sig // Copy value of sig
original := sig original := sig
obj.Signatures[i].header = sig.Header
obj.Signatures[i].original = &original obj.Signatures[i].original = &original
} }
@@ -424,7 +451,10 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
return "", ErrNotSupported return "", ErrNotSupported
} }
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) serializedProtected, err := json.Marshal(obj.Signatures[0].protected)
if err != nil {
return "", err
}
var payload []byte var payload []byte
if !detached { if !detached {
@@ -449,14 +479,23 @@ func (obj JSONWebSignature) DetachedCompactSerialize() (string, error) {
} }
// FullSerialize serializes an object using the full JSON serialization format. // FullSerialize serializes an object using the full JSON serialization format.
//
// It returns "" if obj cannot be serialized.
func (obj JSONWebSignature) FullSerialize() string { func (obj JSONWebSignature) FullSerialize() string {
raw := rawJSONWebSignature{ raw := rawJSONWebSignature{
Payload: newBuffer(obj.payload), Payload: newBuffer(obj.payload),
} }
if len(obj.Signatures) == 0 {
return ""
}
if len(obj.Signatures) == 1 { if len(obj.Signatures) == 1 {
if obj.Signatures[0].protected != nil { if obj.Signatures[0].protected != nil {
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected) serializedProtected, err := json.Marshal(obj.Signatures[0].protected)
if err != nil {
return ""
}
raw.Protected = newBuffer(serializedProtected) raw.Protected = newBuffer(serializedProtected)
} }
raw.Header = obj.Signatures[0].header raw.Header = obj.Signatures[0].header
@@ -470,10 +509,18 @@ func (obj JSONWebSignature) FullSerialize() string {
} }
if signature.protected != nil { if signature.protected != nil {
raw.Signatures[i].Protected = newBuffer(mustSerializeJSON(signature.protected)) serializedProtected, err := json.Marshal(signature.protected)
if err != nil {
return ""
}
raw.Signatures[i].Protected = newBuffer(serializedProtected)
} }
} }
} }
return string(mustSerializeJSON(raw)) out, err := json.Marshal(raw)
if err != nil {
return ""
}
return string(out)
} }
+1 -1
View File
@@ -47,7 +47,7 @@ var ErrNotValidYet = errors.New("go-jose/go-jose/jwt: validation failed, token n
var ErrExpired = errors.New("go-jose/go-jose/jwt: validation failed, token is expired (exp)") var ErrExpired = errors.New("go-jose/go-jose/jwt: validation failed, token is expired (exp)")
// ErrIssuedInTheFuture indicates that the iat field is in the future. // ErrIssuedInTheFuture indicates that the iat field is in the future.
var ErrIssuedInTheFuture = errors.New("go-jose/go-jose/jwt: validation field, token issued in the future (iat)") var ErrIssuedInTheFuture = errors.New("go-jose/go-jose/jwt: validation failed, token issued in the future (iat)")
// ErrInvalidContentType indicates that token requires JWT cty header. // ErrInvalidContentType indicates that token requires JWT cty header.
var ErrInvalidContentType = errors.New("go-jose/go-jose/jwt: expected content type to be JWT (cty header)") var ErrInvalidContentType = errors.New("go-jose/go-jose/jwt: expected content type to be JWT (cty header)")
+12 -17
View File
@@ -85,7 +85,12 @@ func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken,
return sig, nil return sig, nil
} }
// ParseSigned parses token from JWS form. // ParseSigned parses a JWT in the JWS Compact Serialization.
//
// https://datatracker.ietf.org/doc/html/rfc7515#section-3.1
//
// The signatureAlgorithms parameter contains the allowable algorithms in the "alg" header parameter.
// It must be non-empty. Non-matching algorithms cause a parse error.
func ParseSigned(s string, signatureAlgorithms []jose.SignatureAlgorithm) (*JSONWebToken, error) { func ParseSigned(s string, signatureAlgorithms []jose.SignatureAlgorithm) (*JSONWebToken, error) {
sig, err := jose.ParseSignedCompact(s, signatureAlgorithms) sig, err := jose.ParseSignedCompact(s, signatureAlgorithms)
if err != nil { if err != nil {
@@ -142,13 +147,10 @@ func parseEncryptedCompact(
return enc, nil return enc, nil
} }
// ParseEncrypted parses token from JWE form. // ParseEncrypted parses a JWT in the JWE Compact Serialization.
// //
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" // The keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" header in // header parameters respectively. They must be non-empty. Non-matching algorithms cause a parse error.
// parsed data must contain a value that is present in the corresponding parameter. That
// includes the protected and unprotected headers as well as all recipients. To accept
// multiple algorithms, pass a slice of all the algorithms you want to accept.
func ParseEncrypted(s string, func ParseEncrypted(s string,
keyAlgorithms []jose.KeyAlgorithm, keyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption, contentEncryption []jose.ContentEncryption,
@@ -164,17 +166,10 @@ func ParseEncrypted(s string,
}, nil }, nil
} }
// ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form. // ParseSignedAndEncrypted parses a signed-then-encrypted token in the JWE Compact Serialization.
// //
// The encryptionKeyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" // The encryptionKeyAlgorithms, contentEncryption, and signatureAlgorithms parameters contain the allowable
// header parameters, respectively, of the outer JWE. They must be nonempty, and each "alg" or "enc" // algorithms. They must be non-empty. Non-matching algorithms cause a parse error.
// header in parsed data must contain a value that is present in the corresponding parameter. That
// includes the protected and unprotected headers as well as all recipients. To accept
// multiple algorithms, pass a slice of all the algorithms you want to accept.
//
// The signatureAlgorithms parameter is used to validate the "alg" header parameter of the
// inner JWS. It must be nonempty, and the "alg" header in the inner JWS must contain a value
// that is present in the parameter.
func ParseSignedAndEncrypted(s string, func ParseSignedAndEncrypted(s string,
encryptionKeyAlgorithms []jose.KeyAlgorithm, encryptionKeyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption, contentEncryption []jose.ContentEncryption,
+43 -37
View File
@@ -18,6 +18,7 @@ package jose
import ( import (
"crypto/elliptic" "crypto/elliptic"
"crypto/rsa"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
"errors" "errors"
@@ -210,13 +211,20 @@ type Header struct {
// Certificates verifies & returns the certificate chain present // Certificates verifies & returns the certificate chain present
// in the x5c header field of a message, if one was present. Returns // in the x5c header field of a message, if one was present. Returns
// an error if there was no x5c header present or the chain could // an error if there was no x5c header present, any certificate in the
// chain has an RSA key larger than [MaxRSAModulusBits], or the chain could
// not be validated with the given verify options. // not be validated with the given verify options.
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) { func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
if len(h.certificates) == 0 { if len(h.certificates) == 0 {
return nil, ErrMissingX5cHeader return nil, ErrMissingX5cHeader
} }
for _, cert := range h.certificates {
if pub, ok := cert.PublicKey.(*rsa.PublicKey); ok && pub.N.BitLen() > MaxRSAModulusBits {
return nil, fmt.Errorf("go-jose/go-jose: invalid RSA key in x5c certificate, modulus too large")
}
}
leaf := h.certificates[0] leaf := h.certificates[0]
if opts.Intermediates == nil { if opts.Intermediates == nil {
opts.Intermediates = x509.NewCertPool() opts.Intermediates = x509.NewCertPool()
@@ -297,9 +305,10 @@ func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil
} }
var epk *JSONWebKey // RFC 7518 Section 4.6.1.1: the "epk" header is the ephemeral public key
err := json.Unmarshal(*v, &epk) // of the originator. Reject private key material before parsing it.
if err != nil { epk := new(JSONWebKey)
if err := epk.unmarshalJSON(*v, false); err != nil {
return nil, err return nil, err
} }
return epk, nil return epk, nil
@@ -325,20 +334,6 @@ func (parsed rawHeader) getTag() (*byteBuffer, error) {
return parsed.getByteBuffer(headerTag) return parsed.getByteBuffer(headerTag)
} }
// getJWK extracts parsed "jwk" from the raw JSON.
func (parsed rawHeader) getJWK() (*JSONWebKey, error) {
v := parsed[headerJWK]
if v == nil {
return nil, nil
}
var jwk *JSONWebKey
err := json.Unmarshal(*v, &jwk)
if err != nil {
return nil, err
}
return jwk, nil
}
// getCritical extracts parsed "crit" from the raw JSON. If omitted, it // getCritical extracts parsed "crit" from the raw JSON. If omitted, it
// returns an empty slice. // returns an empty slice.
func (parsed rawHeader) getCritical() ([]string, error) { func (parsed rawHeader) getCritical() ([]string, error) {
@@ -424,10 +419,14 @@ func (parsed rawHeader) sanitized() (h Header, err error) {
} }
switch k { switch k {
case headerJWK: case headerJWK:
var jwk *JSONWebKey // RFC 7515 Section 4.1.3 and RFC 7516 Section 4.1.5: the "jwk"
err = json.Unmarshal(*v, &jwk) // header is the public key that corresponds to the key used to
// sign the JWS or encrypt the JWE. Reject private key material
// before parsing it.
jwk := new(JSONWebKey)
err = jwk.unmarshalJSON(*v, false)
if err != nil { if err != nil {
err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v)) err = fmt.Errorf("failed to unmarshal JWK: %w", err)
return return
} }
h.JSONWebKey = jwk h.JSONWebKey = jwk
@@ -499,22 +498,8 @@ func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
} }
func (parsed rawHeader) isSet(k HeaderKey) bool { func (parsed rawHeader) isSet(k HeaderKey) bool {
dvr := parsed[k] _, ok := parsed[k]
if dvr == nil { return ok
return false
}
var dv interface{}
err := json.Unmarshal(*dvr, &dv)
if err != nil {
return true
}
if dvStr, ok := dv.(string); ok {
return dvStr != ""
}
return true
} }
// Merge headers from src into dst, giving precedence to headers from l. // Merge headers from src into dst, giving precedence to headers from l.
@@ -564,3 +549,24 @@ func makeRawMessage(b []byte) *json.RawMessage {
rm := json.RawMessage(b) rm := json.RawMessage(b)
return &rm return &rm
} }
// parseProtectedHeader parses a `byteBuffer` into a `*rawHeader`.
//
// The byteBuffer represents a base64-decoded "protected" header, which
// is specified to contain a JSON object.
//
// If the input is nil or empty, returns `nil, nil`.
//
// `rawHeader` is a map type and so can be nil. When this function
// returns a non-nil `*rawHeader`, the map is guaranteed to be non-nil.
func parseProtectedHeader(in *byteBuffer) (*rawHeader, error) {
if in == nil || len(in.bytes()) == 0 {
return nil, nil
}
var header rawHeader
err := json.Unmarshal(in.bytes(), &header)
if err != nil || header == nil {
return nil, errors.New("go-jose/go-jose: invalid protected header")
}
return &header, nil
}
+4 -1
View File
@@ -321,7 +321,10 @@ func (ctx *genericSigner) Sign(payload []byte) (*JSONWebSignature, error) {
protected[k] = v protected[k] = v
} }
serializedProtected := mustSerializeJSON(protected) serializedProtected, err := json.Marshal(protected)
if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: Error marshaling JSON: %s", err)
}
needsBase64 := true needsBase64 := true
if b64, ok := protected[headerB64]; ok { if b64, ok := protected[headerB64]; ok {
+1 -1
View File
@@ -421,7 +421,7 @@ func (ctx *symmetricKeyCipher) decryptKey(headers rawHeader, recipient *recipien
if err != nil { if err != nil {
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err) return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: %v", err)
} }
if p2s == nil || len(p2s.data) == 0 { if p2s == nil || len(p2s.bytes()) == 0 {
return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present") return nil, fmt.Errorf("go-jose/go-jose: invalid P2S: must be present")
} }
+13
View File
@@ -0,0 +1,13 @@
# This containerfile can be used to run the go-jose tests and cli
FROM golang:1.27-trixie
ENV GOTOOLCHAIN=local
COPY . /src
WORKDIR /src
# Install the jose-util cli, which will also build the library
RUN go build -o /usr/local/bin/jose-util ./jose-util
# By default, run the tests
CMD ["go", "test", "./..."]
+25
View File
@@ -0,0 +1,25 @@
# Threat model
## What this project does and where untrusted input enters
go-jose is a Go implementation of JOSE family of algorithms.
It is a library which will parse attacker-controlled data in network-reachable
services.
## Components that matter most / least
The primary attack surface of interest is parsing and validating JWS, JWE, JWK,
etc when this library is used to implement authentication and authorization.
## How to exercise it
Testing is primarily done by Golang unit tests, which can be run with the
tests.Container file's default CMD.
## How you rate severity
Any authentication bypass enabled by a go-jose issue is a high+ severity.
Denial-of-service attacks are of interest when the functions may be used in a protocol like OIDC, ACME, etc
which could have a server processing attacker-controlled data.
## Anything to leave alone
Any bug which only affects the jose-util CLI tool, but it can be used to exercise the library.
+2 -1
View File
@@ -659,7 +659,8 @@ func (s *Scratch) validateNorm() (err error) {
if v >= 0 { if v >= 0 {
total += int(v) total += int(v)
} else { } else {
total -= int(v) // -1 takes one cell. Adding -v would let a wrapped -32768 pass.
total++
} }
} }
defer func() { defer func() {
+6
View File
@@ -3,6 +3,7 @@ package fse
import ( import (
"errors" "errors"
"fmt" "fmt"
"math"
) )
const ( const (
@@ -123,6 +124,11 @@ func (s *Scratch) readNCount() error {
remaining -= count remaining -= count
gotTotal += count gotTotal += count
} }
if count > math.MaxInt16 {
// Only one symbol filling a tableLog 15 table, which cannot be decoded.
// Truncated, it would leave the decoding table unwritten.
return fmt.Errorf("corruption detected (count %d > %d)", count, math.MaxInt16)
}
s.norm[charnum&0xff] = int16(count) s.norm[charnum&0xff] = int16(count)
charnum++ charnum++
previous0 = count == 0 previous0 = count == 0
+4
View File
@@ -54,6 +54,10 @@ func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) {
if len(in) < int(iSize) { if len(in) < int(iSize) {
return s, nil, fmt.Errorf("input too small for table, want %d bytes, have %d", iSize, len(in)) return s, nil, fmt.Errorf("input too small for table, want %d bytes, have %d", iSize, len(in))
} }
// The low nibble is the weights' FSE tableLog - 5, which the format limits to 6.
if in[0]&15+5 > 6 {
return s, nil, errors.New("corrupt input: weights tableLog too big")
}
// FSE compressed weights // FSE compressed weights
s.fse.DecompressLimit = 255 s.fse.DecompressLimit = 255
hw := s.huffWeight[:] hw := s.huffWeight[:]
+3
View File
@@ -219,6 +219,9 @@ func BuildDict(o BuildDictOptions) ([]byte, error) {
if len(contents) == 0 { if len(contents) == 0 {
return nil, errors.New("no content provided") return nil, errors.New("no content provided")
} }
if o.Level < speedNotSet || o.Level >= speedLast {
return nil, fmt.Errorf("unknown encoder level %d", o.Level)
}
d := dict{ d := dict{
id: o.ID, id: o.ID,
litEnc: nil, litEnc: nil,
+12
View File
@@ -69,6 +69,10 @@ var (
// No CRC value is being generated and not all CRC values of the Snappy stream are checked. // No CRC value is being generated and not all CRC values of the Snappy stream are checked.
// However, it provides really fast recompression of Snappy streams. // However, it provides really fast recompression of Snappy streams.
// The converter can be reused to avoid allocations, even after errors. // The converter can be reused to avoid allocations, even after errors.
//
// Deprecated: Decode the stream with s2.NewReader, which reads Snappy streams,
// and compress the output with an Encoder. This validates the input and
// compresses much better.
type SnappyConverter struct { type SnappyConverter struct {
r io.Reader r io.Reader
err error err error
@@ -373,6 +377,14 @@ func decodeSnappy(blk *blockEnc, src []byte) error {
offset = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 offset = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24
} }
// A zstd match is at least zstdMinMatch bytes. A shorter copy
// cannot be represented as a sequence and would underflow the
// matchLen computation below, producing an out-of-range match
// length code.
if length < zstdMinMatch {
return ErrSnappyCorrupt
}
if offset <= 0 || blk.size+lits < int(offset) /*|| length > len(blk)-d */ { if offset <= 0 || blk.size+lits < int(offset) /*|| length > len(blk)-d */ {
println("offset <= 0 || blk.size+lits < int(offset)", offset, blk.size+lits, int(offset), blk.size, lits) println("offset <= 0 || blk.size+lits < int(offset)", offset, blk.size+lits, int(offset), blk.size, lits)
+1
View File
@@ -52,6 +52,7 @@ func (es *EndpointSettings) Copy() *EndpointSettings {
epCopy.Aliases = slices.Clone(es.Aliases) epCopy.Aliases = slices.Clone(es.Aliases)
epCopy.DNSNames = slices.Clone(es.DNSNames) epCopy.DNSNames = slices.Clone(es.DNSNames)
epCopy.DriverOpts = maps.Clone(es.DriverOpts) epCopy.DriverOpts = maps.Clone(es.DriverOpts)
epCopy.MacAddress = slices.Clone(es.MacAddress)
return &epCopy return &epCopy
} }
-1
View File
@@ -1 +0,0 @@
testdata/rapid/**
+2 -2
View File
@@ -108,7 +108,7 @@ const DummyHost = "api.moby.localhost"
// overriding the version and disable API-version negotiation. // overriding the version and disable API-version negotiation.
// //
// This version may be lower than the version of the api library module used. // This version may be lower than the version of the api library module used.
const MaxAPIVersion = "1.56" const MaxAPIVersion = "1.57"
// MinAPIVersion is the minimum API version supported by the client. API versions // MinAPIVersion is the minimum API version supported by the client. API versions
// below this version are not considered when performing API-version negotiation. // below this version are not considered when performing API-version negotiation.
@@ -436,7 +436,7 @@ func (cli *Client) dialer() func(context.Context) (net.Conn, error) {
return dialPipeContext(ctx, cli.addr) return dialPipeContext(ctx, cli.addr)
default: default:
if tlsConfig := cli.tlsConfig(); tlsConfig != nil { if tlsConfig := cli.tlsConfig(); tlsConfig != nil {
return tls.Dial(cli.proto, cli.addr, tlsConfig) return (&tls.Dialer{Config: tlsConfig}).DialContext(ctx, cli.proto, cli.addr)
} }
return net.Dial(cli.proto, cli.addr) return net.Dial(cli.proto, cli.addr)
} }
+3 -1
View File
@@ -100,8 +100,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (retConn net
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
// Closing the body ends the otelhttp span. A 101 response has no body,
// so this does not close the connection.
_ = resp.Body.Close()
if resp.StatusCode != http.StatusSwitchingProtocols { if resp.StatusCode != http.StatusSwitchingProtocols {
_ = resp.Body.Close()
return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode) return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode)
} }
+60 -9
View File
@@ -22,7 +22,7 @@ file {
java_package: "com.google.protobuf" java_package: "com.google.protobuf"
java_outer_classname: "TimestampProto" java_outer_classname: "TimestampProto"
java_multiple_files: true java_multiple_files: true
go_package: "github.com/golang/protobuf/ptypes/timestamp" go_package: "google.golang.org/protobuf/types/known/timestamppb"
cc_enable_arenas: true cc_enable_arenas: true
objc_class_prefix: "GPB" objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes" csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -53,7 +53,7 @@ file {
java_package: "com.google.protobuf" java_package: "com.google.protobuf"
java_outer_classname: "DurationProto" java_outer_classname: "DurationProto"
java_multiple_files: true java_multiple_files: true
go_package: "github.com/golang/protobuf/ptypes/duration" go_package: "google.golang.org/protobuf/types/known/durationpb"
cc_enable_arenas: true cc_enable_arenas: true
objc_class_prefix: "GPB" objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes" csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -157,7 +157,7 @@ file {
java_package: "com.google.protobuf" java_package: "com.google.protobuf"
java_outer_classname: "WrappersProto" java_outer_classname: "WrappersProto"
java_multiple_files: true java_multiple_files: true
go_package: "github.com/golang/protobuf/ptypes/wrappers" go_package: "google.golang.org/protobuf/types/known/wrapperspb"
cc_enable_arenas: true cc_enable_arenas: true
objc_class_prefix: "GPB" objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes" csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -484,6 +484,13 @@ file {
type_name: ".google.protobuf.FieldOptions" type_name: ".google.protobuf.FieldOptions"
json_name: "options" json_name: "options"
} }
field {
name: "proto3_optional"
number: 17
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "proto3Optional"
}
enum_type { enum_type {
name: "Type" name: "Type"
value { value {
@@ -853,7 +860,7 @@ file {
number: 31 number: 31
label: LABEL_OPTIONAL label: LABEL_OPTIONAL
type: TYPE_BOOL type: TYPE_BOOL
default_value: "false" default_value: "true"
json_name: "ccEnableArenas" json_name: "ccEnableArenas"
} }
field { field {
@@ -1405,7 +1412,7 @@ file {
java_package: "com.google.protobuf" java_package: "com.google.protobuf"
java_outer_classname: "DescriptorProtos" java_outer_classname: "DescriptorProtos"
optimize_for: SPEED optimize_for: SPEED
go_package: "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor" go_package: "google.golang.org/protobuf/types/descriptorpb"
cc_enable_arenas: true cc_enable_arenas: true
objc_class_prefix: "GPB" objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.Reflection" csharp_namespace: "Google.Protobuf.Reflection"
@@ -5208,7 +5215,7 @@ file {
java_package: "com.google.protobuf" java_package: "com.google.protobuf"
java_outer_classname: "AnyProto" java_outer_classname: "AnyProto"
java_multiple_files: true java_multiple_files: true
go_package: "github.com/golang/protobuf/ptypes/any" go_package: "google.golang.org/protobuf/types/known/anypb"
objc_class_prefix: "GPB" objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes" csharp_namespace: "Google.Protobuf.WellKnownTypes"
} }
@@ -10590,7 +10597,7 @@ file {
syntax: "proto3" syntax: "proto3"
} }
file { file {
name: "go.etcd.io/etcd/raft/v3/raftpb/raft.proto" name: "go.etcd.io/raft/v3/raftpb/raft.proto"
package: "raftpb" package: "raftpb"
dependency: "gogoproto/gogo.proto" dependency: "gogoproto/gogo.proto"
message_type { message_type {
@@ -10773,6 +10780,16 @@ file {
} }
json_name: "commit" json_name: "commit"
} }
field {
name: "vote"
number: 13
label: LABEL_OPTIONAL
type: TYPE_UINT64
options {
65001: 0
}
json_name: "vote"
}
field { field {
name: "snapshot" name: "snapshot"
number: 9 number: 9
@@ -10780,7 +10797,7 @@ file {
type: TYPE_MESSAGE type: TYPE_MESSAGE
type_name: ".raftpb.Snapshot" type_name: ".raftpb.Snapshot"
options { options {
65001: 0 65001: 1
} }
json_name: "snapshot" json_name: "snapshot"
} }
@@ -10809,8 +10826,22 @@ file {
number: 12 number: 12
label: LABEL_OPTIONAL label: LABEL_OPTIONAL
type: TYPE_BYTES type: TYPE_BYTES
options {
65001: 1
}
json_name: "context" json_name: "context"
} }
field {
name: "responses"
number: 14
label: LABEL_REPEATED
type: TYPE_MESSAGE
type_name: ".raftpb.Message"
options {
65001: 0
}
json_name: "responses"
}
} }
message_type { message_type {
name: "HardState" name: "HardState"
@@ -11079,6 +11110,26 @@ file {
name: "MsgPreVoteResp" name: "MsgPreVoteResp"
number: 18 number: 18
} }
value {
name: "MsgStorageAppend"
number: 19
}
value {
name: "MsgStorageAppendResp"
number: 20
}
value {
name: "MsgStorageApply"
number: 21
}
value {
name: "MsgStorageApplyResp"
number: 22
}
value {
name: "MsgForgetLeader"
number: 23
}
} }
enum_type { enum_type {
name: "ConfChangeTransition" name: "ConfChangeTransition"
@@ -11130,7 +11181,7 @@ file {
package: "docker.swarmkit.v1" package: "docker.swarmkit.v1"
dependency: "github.com/docker/swarmkit/api/objects.proto" dependency: "github.com/docker/swarmkit/api/objects.proto"
dependency: "github.com/docker/swarmkit/api/types.proto" dependency: "github.com/docker/swarmkit/api/types.proto"
dependency: "go.etcd.io/etcd/raft/v3/raftpb/raft.proto" dependency: "go.etcd.io/raft/v3/raftpb/raft.proto"
dependency: "gogoproto/gogo.proto" dependency: "gogoproto/gogo.proto"
dependency: "github.com/docker/swarmkit/protobuf/plugin/plugin.proto" dependency: "github.com/docker/swarmkit/protobuf/plugin/plugin.proto"
message_type { message_type {
+2 -2
View File
@@ -12,7 +12,7 @@ type CopierFrom interface {
// Copy takes the fields from src and copies them into the target object. // Copy takes the fields from src and copies them into the target object.
// //
// Calling this method with a nil receiver or a nil src may panic. // Calling this method with a nil receiver or a nil src may panic.
CopyFrom(src interface{}) CopyFrom(src any)
} }
// Copy copies src into dst. dst and src must have the same type. // Copy copies src into dst. dst and src must have the same type.
@@ -24,7 +24,7 @@ type CopierFrom interface {
// //
// If the copy cannot be performed, this function will panic. Make sure to test // If the copy cannot be performed, this function will panic. Make sure to test
// types that use this function. // types that use this function.
func Copy(dst, src interface{}) { func Copy(dst, src any) {
switch dst := dst.(type) { switch dst := dst.(type) {
case *types.Any: case *types.Any:
src := src.(*types.Any) src := src.(*types.Any)
+2 -2
View File
@@ -73,7 +73,7 @@ func customIndexer(kind string, annotations *Annotations) (bool, [][]byte, error
return len(converted) != 0, converted, nil return len(converted) != 0, converted, nil
} }
func fromArgs(args ...interface{}) ([]byte, error) { func fromArgs(args ...any) ([]byte, error) {
if len(args) != 1 { if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument") return nil, fmt.Errorf("must provide only a single argument")
} }
@@ -86,7 +86,7 @@ func fromArgs(args ...interface{}) ([]byte, error) {
return []byte(arg), nil return []byte(arg), nil
} }
func prefixFromArgs(args ...interface{}) ([]byte, error) { func prefixFromArgs(args ...any) ([]byte, error) {
val, err := fromArgs(args...) val, err := fromArgs(args...)
if err != nil { if err != nil {
return nil, err return nil, err

Some files were not shown because too many files have changed in this diff Show More