Compare commits

...
Author SHA1 Message Date
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 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
260 changed files with 9086 additions and 2342 deletions
+3 -3
View File
@@ -68,7 +68,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
-
name: Build
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with:
targets: ${{ matrix.target }}
set: |
@@ -99,7 +99,7 @@ jobs:
bin-image:
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@cbc9d42f8c89a55623392aadd03600965b80e963 # v1.18.1
permissions:
contents: read # same as global permission
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
-
name: Build
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with:
targets: plugins-cross
set: |
+4 -4
View File
@@ -64,18 +64,18 @@ jobs:
name: Update Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26.10"
go-version: "1.27.3"
cache: false
-
name: Initialize CodeQL
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: go
-
name: Autobuild
uses: github/codeql-action/autobuild@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
uses: github/codeql-action/autobuild@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
category: "/language:go"
+4 -1
View File
@@ -26,6 +26,9 @@ on:
jobs:
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
strategy:
fail-fast: false
@@ -80,4 +83,4 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
files: ./build/coverage/coverage.txt
token: ${{ secrets.CODECOV_TOKEN }}
use_oidc: true
+1 -1
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
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:
contents: read # Read repository files and PR diffs
pull-requests: write # Post review comments
+12 -6
View File
@@ -26,6 +26,9 @@ on:
jobs:
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
steps:
-
@@ -33,7 +36,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
-
name: Test
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with:
targets: test-coverage
-
@@ -41,9 +44,12 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
files: ./build/coverage/coverage.txt
token: ${{ secrets.CODECOV_TOKEN }}
use_oidc: true
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 }}
env:
GOPATH: ${{ github.workspace }}
@@ -53,9 +59,9 @@ jobs:
fail-fast: false
matrix:
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-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
steps:
-
@@ -68,7 +74,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26.10"
go-version: "1.27.3"
cache: false
-
name: Test
@@ -86,4 +92,4 @@ jobs:
with:
files: /tmp/coverage.txt
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:
-
name: Run
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
with:
targets: ${{ matrix.target }}
@@ -101,7 +101,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26.10"
go-version: "1.27.3"
cache: false
-
name: Run gocompat check
+1 -11
View File
@@ -5,7 +5,7 @@ run:
# which causes it to fallback to go1.17 semantics.
#
# TODO(thaJeztah): update "usetesting" settings to enable go1.24 features once our minimum version is go1.24
go: "1.26.10"
go: "1.27.3"
timeout: 5m
@@ -201,11 +201,6 @@ linters:
linters:
- 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.
- path: _test\.go
linters:
@@ -227,11 +222,6 @@ linters:
linters:
- 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.
# Default: false
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.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23
ARG BASE_DEBIAN_DISTRO=bookworm
ARG ALPINE_VERSION=3.24
ARG GO_VERSION=1.26.10
# BASE_DEBIAN_DISTRO sets the version of the debian base image to use,
ARG BASE_DEBIAN_DISTRO=trixie
ARG GO_VERSION=1.27.3
# 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.
@@ -25,12 +27,12 @@ ARG GOTESTSUM_VERSION=v1.13.0
# BUILDX_VERSION sets the version of buildx to use for the e2e tests.
# It must be a tag in the docker.io/docker/buildx-bin image repository
# on Docker Hub.
ARG BUILDX_VERSION=0.38.0
ARG BUILDX_VERSION=0.38.1
# 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
# on Docker Hub.
ARG COMPOSE_VERSION=v5.6.0
ARG COMPOSE_VERSION=v5.7.0
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
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
ARG GOVERSIONINFO_VERSION
+62 -2
View File
@@ -10,6 +10,7 @@ import (
"fmt"
"os"
"sync"
"time"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/metadata"
@@ -32,6 +33,11 @@ import (
// called.
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
func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) error {
tcmd := newPluginCommand(dockerCli, plugin, meta)
@@ -69,6 +75,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadat
stopInstrumentation(err)
return err
}
cobra.OnFinalize(func() { finalizeHook(dockerCli) })
})
return retErr
}
@@ -83,6 +90,59 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadat
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
// be called from the plugin's "main()" function. It initializes a new
// [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,
Hidden: true,
// Suppress the global/parent PersistentPreRunE, which
// needlessly initializes the client and tries to
// connect to the daemon.
// needlessly initializes the client and tries to connect to the
// daemon.
PersistentPreRun: func(cmd *cobra.Command, args []string) {},
RunE: func(cmd *cobra.Command, args []string) error {
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 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.
+42
View File
@@ -108,3 +108,45 @@ func TestDecoratedName(t *testing.T) {
topLevelCommand.Annotations = map[string]string{metadata.CommandAnnotationPlugin: "true"}
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
// legacy `--link` feature) are omitted when formatting "truncated".
func (c *ContainerContext) Names() string {
var b strings.Builder
for i, n := range c.c.Names {
name := strings.TrimPrefix(n, "/")
if c.trunc {
// When printing truncated, we only print a single name.
//
// Pick the first name that's not a legacy link (does not have
// slashes inside the name itself (e.g., "/other-container/link")).
// Normally this would be the first name found.
if strings.IndexByte(name, '/') == -1 {
if c.trunc {
// When printing truncated, we only print a single name.
//
// Pick the first name that's not a legacy link (does not have
// slashes inside the name itself (e.g., "/other-container/link")).
// Normally this would be the first name found.
for _, n := range c.c.Names {
if name := strings.TrimPrefix(n, "/"); strings.IndexByte(name, '/') == -1 {
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 {
b.WriteByte(',')
}
b.WriteString(name)
b.WriteString(strings.TrimPrefix(n, "/"))
}
return b.String()
}
+20
View File
@@ -48,6 +48,25 @@ func TestContainerPsContext(t *testing.T) {
expValue: "foobar_baz",
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"},
trunc: true,
@@ -257,6 +276,7 @@ func TestContainerPsContext(t *testing.T) {
}
}
//nolint:dupword // ignore duplicate "ubuntu" in test fixtures
func TestContainerContextWrite(t *testing.T) {
unixTime := time.Now().AddDate(0, 0, -1).Unix()
expectedTime := time.Unix(unixTime, 0).String()
+30 -2
View File
@@ -10,8 +10,10 @@ import (
"slices"
"github.com/containerd/errdefs"
"github.com/containerd/platforms"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/manifest/store"
"github.com/docker/cli/internal/registryclient"
@@ -20,6 +22,23 @@ import (
"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 {
target string // the target manifest list name (also transaction ID)
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.StringVar(&opts.variant, "variant", "", "Set architecture variant")
_ = cmd.RegisterFlagCompletionFunc("os", completion.FromList(knownOSes...))
_ = cmd.RegisterFlagCompletionFunc("arch", completion.FromList(knownArches...))
return cmd
}
@@ -139,8 +160,15 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error {
imageManifest.Descriptor.Platform.OSVersion = opts.osVersion
}
if !isValidOSArch(imageManifest.Descriptor.Platform.OS, imageManifest.Descriptor.Platform.Architecture) {
return fmt.Errorf("manifest entry for image has unsupported os/arch combination: %s/%s", opts.os, opts.arch)
// Validate platform syntax, without restricting OS/architecture combinations.
//
// 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)
}
+8 -7
View File
@@ -58,15 +58,16 @@ func TestManifestAnnotate(t *testing.T) {
assert.ErrorContains(t, cmd.Execute(), expectedError)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.Flags().Set("os", "freebsd")
cmd.Flags().Set("arch", "fake")
cmd.Flags().Set("os-version", "1")
cmd.Flags().Set("os-features", "feature1")
cmd.Flags().Set("variant", "v7")
expectedError = "manifest entry for image has unsupported os/arch combination"
assert.NilError(t, cmd.Flags().Set("os", "freebsd"))
assert.NilError(t, cmd.Flags().Set("arch", "<invalid>"))
assert.NilError(t, cmd.Flags().Set("os-version", "1"))
assert.NilError(t, cmd.Flags().Set("os-features", "feature1"))
assert.NilError(t, cmd.Flags().Set("variant", "v7"))
expectedError = "manifest entry for image has invalid platform"
assert.ErrorContains(t, cmd.Execute(), expectedError)
cmd.Flags().Set("arch", "arm")
assert.NilError(t, cmd.Flags().Set("arch", "arm"))
assert.NilError(t, cmd.Execute())
cmd = newInspectCommand(cli)
-47
View File
@@ -9,53 +9,6 @@ import (
"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) {
namedRef, err := reference.ParseNormalizedNamed(ref)
if err != nil {
+2 -2
View File
@@ -210,9 +210,9 @@ func TestResourceOptionsToResourceRequirementsSwap(t *testing.T) {
r, err = swapOptions.ToResourceRequirements(flags)
assert.NilError(t, err)
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, is.Equal(*(r.MemorySwappiness), int64(23)))
assert.Check(t, is.Equal(*r.MemorySwappiness, int64(23)))
}
func TestToServiceNetwork(t *testing.T) {
+2 -2
View File
@@ -20,7 +20,7 @@ import (
"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.
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
// so if there's some kind of issue we need to abort pretty
// quickly.
ctx, cancel := context.WithTimeout(ctx, exportTimeout)
ctx, cancel := context.WithTimeout(ctx, ExportTimeout)
defer cancel()
return r.ForceFlush(ctx)
+1 -1
View File
@@ -109,7 +109,7 @@ func dockerSpanExporter(ctx context.Context, cli Cli) []sdktrace.TracerProviderO
otel.Handle(err)
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 {
+1 -1
View File
@@ -85,7 +85,7 @@ func startCobraCommandTimer(mp metric.MeterProvider, attrs []attribute.KeyValue)
return func(err error) {
// 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(), exportTimeout)
ctx, cancel := context.WithTimeout(context.Background(), ExportTimeout)
defer cancel()
duration := float64(time.Since(start)) / float64(time.Millisecond)
-4
View File
@@ -255,7 +255,6 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
return nil
}
//nolint:unparam
func mergeUlimitsConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().Set(src.Elem())
@@ -263,7 +262,6 @@ func mergeUlimitsConfig(dst, src reflect.Value) error {
return nil
}
//nolint:unparam
func mergeShellCommand(dst, src reflect.Value) error {
if src.Len() != 0 {
dst.Set(src)
@@ -271,7 +269,6 @@ func mergeShellCommand(dst, src reflect.Value) error {
return nil
}
//nolint:unparam
func mergeServiceNetworkConfig(dst, src reflect.Value) error {
if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() {
dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases"))
@@ -285,7 +282,6 @@ func mergeServiceNetworkConfig(dst, src reflect.Value) error {
return nil
}
//nolint:unparam
func mergeUint64(dst, src reflect.Value) error {
if !src.IsNil() {
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)
r, _, err := os.Pipe()
r, w, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r))
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
time.Sleep(100 * time.Microsecond)
+1
View File
@@ -4156,6 +4156,7 @@ _docker_manifest_annotate() {
amd64
arm
arm64
loong64
mips64
mips64le
ppc64le
+1 -1
View File
@@ -2,7 +2,7 @@
# 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.
ARG ALPINE_VERSION=3.23
ARG ALPINE_VERSION=3.24
FROM alpine:${ALPINE_VERSION} AS gen
RUN apk add --no-cache bash git
+3 -3
View File
@@ -1,16 +1,16 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.10
ARG GO_VERSION=1.27.3
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23
ARG ALPINE_VERSION=3.24
# 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
# on Docker Hub.
ARG BUILDX_VERSION=0.38.0
ARG BUILDX_VERSION=0.38.1
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang
+3 -3
View File
@@ -1,13 +1,13 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.10
ARG GO_VERSION=1.27.3
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23
ARG ALPINE_VERSION=3.24
# 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
+3 -3
View File
@@ -1,12 +1,12 @@
# syntax=docker/dockerfile:1
ARG GO_VERSION=1.26.10
ARG GO_VERSION=1.27.3
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
# It must be a supported tag in the docker.io/library/alpine image repository
# that's also available as alpine image variant for the Golang version used.
ARG ALPINE_VERSION=3.23
ARG MODOUTDATED_VERSION=v0.8.0
ARG ALPINE_VERSION=3.24
ARG MODOUTDATED_VERSION=v0.9.0
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
ENV GOTOOLCHAIN=local
@@ -44,8 +44,8 @@ created. Supported `Dockerfile` instructions:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.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
c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
$ docker commit c3f279d17e0a svendowideit/testimage:version3
@@ -63,8 +63,8 @@ svendowideit/testimage version3 f5283438590d 16 sec
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.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
c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
197387f1b436 ubuntu:26.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
$ docker inspect -f "{{ .Config.Env }}" c3f279d17e0a
@@ -85,8 +85,8 @@ $ docker inspect -f "{{ .Config.Env }}" f5283438590d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c3f279d17e0a ubuntu:24.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
c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
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
@@ -100,6 +100,6 @@ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
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
197387f1b436 ubuntu:24.04 /bin/bash 7 days ago Up 25 hours focused_hamilton
c3f279d17e0a ubuntu:26.04 /bin/bash 7 days ago Up 25 hours desperate_dubinsky
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
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
```
@@ -240,13 +240,13 @@ CONTAINER ID IMAGE COMMAND CREATED
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
$ docker ps --filter ancestor=ubuntu:24.04
$ docker ps --filter ancestor=ubuntu:26.04
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
@@ -256,7 +256,7 @@ that have this layer in its layer stack.
$ docker ps --filter ancestor=d0e008c6cf02
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
+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
consists of a single layer; `e756f3fdd6a3`.
Layers can be reused by images. For example, the `debian:bookworm` image shares
its layer with the `debian:latest`. Pulling the `debian:bookworm` image therefore
Layers can be reused by images. For example, the `debian:trixie` image shares
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
locally:
```console
$ docker image pull debian:bookworm
$ docker image pull debian:trixie
bookworm: Pulling from library/debian
trixie: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:bookworm
docker.io/library/debian:bookworm
Status: Downloaded newer image for debian:trixie
docker.io/library/debian:trixie
```
To see which images are present locally, use the [`docker images`](image_ls.md)
@@ -87,13 +87,13 @@ command:
$ docker images
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
```
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,
`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,
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
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.
For example, `docker pull ubuntu:24.04` pulls the latest version of the Ubuntu
24.04 image.
For example, `docker pull ubuntu:26.04` pulls the latest version of the Ubuntu
26.04 image.
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
@@ -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.
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
$ 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
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:26.04
```
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
$ docker image ls --filter reference=ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu jammy 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 24.04 35a88802559d 6 weeks ago 78.1MB
ubuntu 24.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu noble 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 26.04 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
+1 -1
View File
@@ -706,7 +706,7 @@ follows:
| `node.platform.os` | Node operating system | `node.platform.os==windows` |
| `node.platform.arch` | Node architecture | `node.platform.arch==x86_64` |
| `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,
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'
2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 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:26.04)
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)
+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
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
@@ -406,14 +406,14 @@ We have four ways to set user memory usage:
Examples:
```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
as much memory and swap memory as they need.
```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
@@ -421,7 +421,7 @@ the container can use 300M memory and as much swap memory as they need (if the
host supports swap memory).
```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
@@ -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.
```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
@@ -456,7 +456,7 @@ The following example limits the memory (`-m`) to 500M and sets the memory
reservation to 200M.
```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
@@ -466,7 +466,7 @@ memory below 200M.
The following example set memory reservation to 1G without a hard memory limit.
```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
@@ -484,13 +484,13 @@ The following example limits the memory to 100M and disables the OOM killer for
this container:
```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:
```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
@@ -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:
```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
@@ -561,7 +561,7 @@ And usually `--cpu-period` should work with `--cpu-quota`.
Examples:
```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.
@@ -582,13 +582,13 @@ We can set cpus in which to allow execution for containers.
Examples:
```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.
```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.
@@ -599,14 +599,14 @@ on NUMA systems.
Examples:
```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
memory nodes 1 and 3.
```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
@@ -637,8 +637,8 @@ For example, the commands below create two containers with different blkio
weight:
```console
$ docker run -it --name c1 --blkio-weight 300 ubuntu:24.04 /bin/bash
$ docker run -it --name c2 --blkio-weight 600 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:26.04 /bin/bash
```
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.
```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
$ 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
+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
base := &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
}).DialContext,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: endpoint.TLSConfig,
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)
r, _, err := os.Pipe()
r, w, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r))
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
time.Sleep(100 * time.Microsecond)
+2 -2
View File
@@ -48,10 +48,10 @@ Valid placeholders for the Go template are listed below:
$ docker container ls -a
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
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
+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
(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
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.
## 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
consists of a single layer; `e756f3fdd6a3`.
Layers can be reused by images. For example, the `debian:bookworm` image shares
its layer with the `debian:latest`. Pulling the `debian:bookworm` image therefore
Layers can be reused by images. For example, the `debian:trixie` image shares
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
locally:
$ docker image pull debian:bookworm
$ docker image pull debian:trixie
bookworm: Pulling from library/debian
trixie: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:bookworm
docker.io/library/debian:bookworm
Status: Downloaded newer image for debian:trixie
docker.io/library/debian:trixie
To see which images are present locally, use the **docker-images(1)**
command:
@@ -45,12 +45,12 @@ command:
$ docker images
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
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,
`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,
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
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.
For example, `docker image pull ubuntu:24.04` pulls the latest version of the Ubuntu
24.04 image.
For example, `docker image pull ubuntu:26.04` pulls the latest version of the Ubuntu
26.04 image.
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
@@ -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.
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
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:26.04
Docker prints the digest of the image after the pull has finished. In the example
above, the digest of the image is:
@@ -159,11 +159,11 @@ images that are present locally:
$ docker image ls --filter reference=ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu jammy 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 24.04 35a88802559d 6 weeks ago 78.1MB
ubuntu 24.04 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu noble 8a3cdc4d1ad3 3 weeks ago 77.9MB
ubuntu 26.04 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
+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:
# docker events --since '3m'
2015-05-12T11:51:30.999999999Z07:00 4386fb97867d: (from ubuntu:24.04) die
2015-05-12T15:52:12.999999999Z07:00 4386fb97867d: (from ubuntu:24.04) stop
2015-05-12T11:51:30.999999999Z07:00 4386fb97867d: (from ubuntu:26.04) die
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: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
$ 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)
$ docker events --filter 'image=ubuntu:24.04'
2014-05-10T17:42:14.999999999Z07:00 container start 4386fb97867d (image=ubuntu:24.04)
2014-05-10T17:42:14.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04)
$ docker events --filter 'image=ubuntu:26.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:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
$ docker events --filter 'container=7805c1d35632'
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)
$ docker events --filter 'container=7805c1d35632' --filter 'container=4386fb97867d'
2014-09-03T15:49:29.999999999Z07:00 container die 4386fb97867d (image=ubuntu:24.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 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:26.04)
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)
+2 -2
View File
@@ -71,8 +71,8 @@ Server:
seccomp
Profile: builtin
cgroupns
Kernel Version: 5.15.0-25-generic
Operating System: Ubuntu 22.04 LTS
Kernel Version: 6.8.0-31-generic
Operating System: Ubuntu 24.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
+15 -8
View File
@@ -88,13 +88,20 @@ if [ "$CGO_ENABLED" = "1" ] && [ "$(go env GOOS)" != "windows" ]; then
fi
export GO_BUILDMODE
GO_LDFLAGS="${GO_LDFLAGS:-}"
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
# Omit DWARF debug information to reduce binary size, but retain the symbol
# table for tools that inspect Go binaries. Pass GO_LDFLAGS="-w=0" to retain DWARF.
GO_LDFLAGS="-w ${GO_LDFLAGS:-}"
# Quotes are interpreted by Go's -ldflags parser, not the shell.
# shellcheck disable=SC2089
{
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
GO_LDFLAGS="$GO_LDFLAGS -linkmode external -extldflags -static"
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
# llvm-strip: error: unsupported load command (cmd=0x5)
# more info: https://github.com/docker/cli/pull/3717
GO_LDFLAGS="$GO_LDFLAGS -s -w"
GO_LDFLAGS="$GO_LDFLAGS -s"
fi
export GO_LDFLAGS="$GO_LDFLAGS" # https://github.com/koalaman/shellcheck/issues/2064
+27 -26
View File
@@ -21,11 +21,11 @@ require (
github.com/distribution/reference v0.6.0
github.com/docker/cli-docs-tool v0.11.0
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-units v0.5.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/gogo/protobuf v1.3.2
github.com/google/go-cmp v0.7.0
@@ -33,12 +33,12 @@ require (
github.com/google/uuid v1.6.0
github.com/mattn/go-runewidth v0.0.31
github.com/moby/go-archive v0.3.3
github.com/moby/moby/api v1.56.1
github.com/moby/moby/client v0.6.2
github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131
github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131
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/capability v0.4.0
github.com/moby/sys/capability v0.5.0
github.com/moby/sys/sequential v0.7.0
github.com/moby/sys/signal v0.7.1
github.com/moby/sys/symlink v0.3.0
@@ -52,25 +52,25 @@ require (
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/tonistiigi/go-rosetta v0.0.0-20220804170347-3f4430f2d346
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0
go.opentelemetry.io/otel v1.46.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0
go.opentelemetry.io/otel/metric v1.46.0
go.opentelemetry.io/otel/sdk v1.46.0
go.opentelemetry.io/otel/sdk/metric v1.46.0
go.opentelemetry.io/otel/trace v1.46.0
go.yaml.in/yaml/v3 v3.0.5
golang.org/x/sync v0.23.0
golang.org/x/sys v0.48.0
golang.org/x/term v0.46.0
golang.org/x/text v0.42.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0
go.opentelemetry.io/otel v1.47.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0
go.opentelemetry.io/otel/metric v1.47.0
go.opentelemetry.io/otel/sdk v1.47.0
go.opentelemetry.io/otel/sdk/metric v1.47.0
go.opentelemetry.io/otel/trace v1.47.0
go.yaml.in/yaml/v3 v3.0.6
golang.org/x/sync v0.24.0
golang.org/x/sys v0.49.1-0.20261022125458-f5cb0306ac0e // includes fix for https://go.dev/issue/82324
golang.org/x/term v0.47.0
golang.org/x/text v0.43.0
gotest.tools/v3 v3.5.2
tags.cncf.io/container-device-interface v1.1.1
)
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/beorn7/perks v1.0.1 // 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/grpc-ecosystem/grpc-gateway/v2 v2.30.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/sys/user v0.4.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
go.etcd.io/raft/v3 v3.6.0 // 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
golang.org/x/mod v0.41.0 // indirect
golang.org/x/net v0.60.0 // indirect
golang.org/x/mod v0.42.0 // indirect
golang.org/x/net v0.62.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/rpc 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-20260928230214-8a89bd6388cc // indirect
google.golang.org/grpc v1.83.2 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)
+56 -56
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=
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/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 h1:m2xcjRABtG288vnlV3U/PKh/HnPURxZp50RKNUwBxM8=
github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4/go.mod h1:MTUE7ZuZO89FAtAwozGg6AWD83pcdefnEq5gF82MB8s=
github.com/Azure/go-ansiterm v0.0.0-20261013165250-51075c6ea6bc h1:58s5YzGPNAP7+e1uemaL0ax/NPSeJOHdRpRIowd+JDk=
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/go.mod h1:ma0QpxizD4fyyzJ1C7MIblymTD2Nxz5Mho/3CepwIZg=
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/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.9 h1:BkydjIgZ46JnDbqyM2p2fc63KMw6y+KHL3Em/2AGJ7w=
github.com/docker/docker-credential-helpers v0.9.9/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
github.com/docker/docker-credential-helpers v0.9.12 h1:hAgjJcMuC17DPf0Kl/HQSZQ7cxVo+wEA8Oo1SzkmqFg=
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/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
github.com/docker/go-events v0.1.0 h1:J8VX4H7Ta8mmBhv/K/24x1kosKOrEEnYmGjcdFHTOW0=
@@ -51,8 +51,8 @@ github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeO
github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE=
github.com/fvbommel/sortorder v1.2.1 h1:ASc85RbthwLEqzuiCk7WQQiopfyGWQiEYZVJ3Qa4A+U=
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.5/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-jose/go-jose/v4 v4.1.7 h1:Nac/98uT5LPkfbiFuYa8ktf62a2VxwQ4xbq1GK8pV5E=
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.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
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/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/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ=
github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/klauspost/compress v1.20.2 h1:v5tiZvm1KGLyg5d5oXdXe3lsSPrbEUiKoXGia//I7Qo=
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/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
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/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME=
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.1/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk=
github.com/moby/moby/client v0.6.2 h1:ekSPlMccrZGcw6Scb8T9D39qE0mB+XupU/yS0zNw9N4=
github.com/moby/moby/client v0.6.2/go.mod h1:DGcnO7qmPJrqobx/ggQgQ/AUk+2wgVdQv7uxB0/mEsc=
github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131 h1:tPz9ahj8F7AjQw62XQFP65kmoxF3rXTYSit3q06/yQc=
github.com/moby/moby/api v1.56.2-0.20261106011722-402d0a16f131/go.mod h1:pRZ1QRtx6AVhdckeFYo4DUX4ASNF0SCllhyY6aj2mgg=
github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131 h1:ReIO7lalQVE4BetZuIvrxScg8Rxv4Sk74XRs06ryRDU=
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/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/swarmkit/v2 v2.1.2 h1:1WDZAI6HVYNKdCG4zlXnTAPyLsLwuhRGWlHoOUf5Z6I=
github.com/moby/swarmkit/v2 v2.1.2/go.mod h1:GQ6T0ij2oBbWX10OHwpvK449xfXkQMZ8J+B+eQ4mgp4=
github.com/moby/swarmkit/v2 v2.1.3 h1:UcwtwkIRjr75qSgUWCTIuzKUzAXlidxsiqVMnyxSF1w=
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/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
github.com/moby/sys/capability v0.5.0 h1:Bm4oD9xGCtZguPnaoQy1/jvKTSwZHMvM0FrnxNYtGYU=
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/go.mod h1:WUQDO+/uCiCIkIztx8SrwIDVn2dtMFRBebRhpDFT71M=
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.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/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0 h1:qkDYCAFiZXLcs1L4aY+tP2wguQ4kURANqHOQMA2et2s=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.46.0/go.mod h1:tkipS4DRzmpAmvg+Gw4++O1IdDq6TVDnvnYU6cmbQVs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 h1:OFnwLJr+pF3iHrlGSzbxyuo6/6HyBlnlN1CWEJmBVcw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0/go.mod h1:716wFneO0ov19A2beH5hjfh9AK5z/VWNAtDijp1Y0/g=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0 h1:w53CDeOA/Kurp7yRsegSr6pbbr759dOvJ+yNmWM6Hxs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.46.0/go.mod h1:BOmGMCbAtvcJiSJ+hLuhgPLdDbimnraSl8irz3iY8sY=
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
go.opentelemetry.io/otel/metric/x v0.68.0 h1:TA/cBT23D3MnxYPwHL7YFOdYGdx0A0v+s7Mzotpd1dU=
go.opentelemetry.io/otel/metric/x v0.68.0/go.mod h1:agudOmvWhwUTjgibWDzxD2PoWYnpw5Ht5jISYOD2Hd4=
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM=
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4=
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
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.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw=
go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM=
go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0 h1:LaLVGJtIzHcvHjVs2OftmKcc+M9mdOqS8vZ1fBD1Yes=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.47.0/go.mod h1:vF6H5sNDuQBJWgSX00iZgbIqk2MZZoVMH0ar5t5bOpw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0 h1:julhjPeUH/q/7hinbSdDdqt5h7Zw9YWmRlWRhI0jd54=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.47.0/go.mod h1:Ao2mz688LH/tFf0yMAenidq6k2YNSx6SIY2q6jDACck=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0 h1:UFpxOpYPmMNUtOWhdb+nC1WELIgVf8z9higURrbzYU4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.47.0/go.mod h1:YBGjxe3lt0jtXoEXxGrGhv/jM7oUBUDVK7zhAvNyEjc=
go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI=
go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw=
go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY=
go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU=
go.opentelemetry.io/otel/metric/x v0.69.0 h1:DjRLr15H83v+hCW7JA9NoJvOkYTtmq5YoDRbe9deYpM=
go.opentelemetry.io/otel/metric/x v0.69.0/go.mod h1:uVvsMPMFFyj/HUQfrUnH3JjnOQ1dwFDorgFLRBasM0k=
go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I=
go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0=
go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw=
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/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
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.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
go.yaml.in/yaml/v3 v3.0.6 h1:zcDfvjXEqTQmpjniUBLc91xYJMB2c4QOFxEF/LCEckM=
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c=
golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
golang.org/x/mod v0.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg=
golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs=
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-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.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU=
golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
golang.org/x/net v0.62.0 h1:18ELalfM5+XNRwzM2nYqXsZQ9ByS1uhj2O/U7+5jqRY=
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-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.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
golang.org/x/sync v0.24.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-20190412213103-97732733099d/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.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE=
golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc=
golang.org/x/sys v0.49.1-0.20261022125458-f5cb0306ac0e h1:y3PdhEKVIFYc4c6gNZPEC7qPIoa9uH/2zIQEc0mw4R4=
golang.org/x/sys v0.49.1-0.20261022125458-f5cb0306ac0e/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM=
golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY=
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.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
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/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=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
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-20260825221802-da73d73af1c5/go.mod h1:3LhxRw4YYkf+ylAfgaY9JlVLFKhokkCV8duhLLe7+t0=
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-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
google.golang.org/genproto/googleapis/api v0.0.0-20260928230214-8a89bd6388cc h1:rZHRz0ogq4Pid1IKtA/ivHi8XONVF5tqUQXA2TtgpkE=
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-20260928230214-8a89bd6388cc h1:4bNTbnb44EqGVy9HaQxSY2jnafSUdgV3qHtedvNpDKg=
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/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
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=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
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/go.mod h1:S1PSJWYPD4Iom0/39mvr/VVFCfG0Yt14j20d0OYrY2M=
+7 -5
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type csiEntryState struct {
baseState
}
@@ -13,11 +15,11 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
}
switch {
case sliceContains(alphabetics, b):
case slices.Contains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
case slices.Contains(csiCollectables, b):
return csiState.parser.csiParam, nil
case sliceContains(executors, b):
case slices.Contains(executors, b):
return csiState, csiState.parser.execute()
}
@@ -33,9 +35,9 @@ func (csiState csiEntryState) Transition(s state) error {
return csiState.parser.csiDispatch()
case csiState.parser.csiParam:
switch {
case sliceContains(csiParams, csiState.parser.context.currentChar):
case slices.Contains(csiParams, csiState.parser.context.currentChar):
_ = csiState.parser.collectParam()
case sliceContains(intermeds, csiState.parser.context.currentChar):
case slices.Contains(intermeds, csiState.parser.context.currentChar):
_ = csiState.parser.collectInter()
}
}
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type csiParamState struct {
baseState
}
@@ -13,11 +15,11 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
}
switch {
case sliceContains(alphabetics, b):
case slices.Contains(alphabetics, b):
return csiState.parser.ground, nil
case sliceContains(csiCollectables, b):
case slices.Contains(csiCollectables, b):
return csiState, csiState.parser.collectParam()
case sliceContains(executors, b):
case slices.Contains(executors, b):
return csiState, csiState.parser.execute()
}
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type escapeIntermediateState struct {
baseState
}
@@ -12,11 +14,11 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
}
switch {
case sliceContains(intermeds, b):
case slices.Contains(intermeds, b):
return escState, escState.parser.collectInter()
case sliceContains(executors, b):
case slices.Contains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeIntermediateToGroundBytes, b):
case slices.Contains(escapeIntermediateToGroundBytes, b):
return escState.parser.ground, nil
}
+5 -3
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type escapeState struct {
baseState
}
@@ -16,11 +18,11 @@ func (escState escapeState) Handle(b byte) (s state, e error) {
return escState.parser.csiEntry, nil
case b == ANSI_OSC_STRING_ENTRY:
return escState.parser.oscString, nil
case sliceContains(executors, b):
case slices.Contains(executors, b):
return escState, escState.parser.execute()
case sliceContains(escapeToGroundBytes, b):
case slices.Contains(escapeToGroundBytes, b):
return escState.parser.ground, nil
case sliceContains(intermeds, b):
case slices.Contains(intermeds, b):
return escState.parser.escapeIntermediate, nil
}
+4 -2
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type groundState struct {
baseState
}
@@ -13,10 +15,10 @@ func (gs groundState) Handle(b byte) (s state, e error) {
}
switch {
case sliceContains(printables, b):
case slices.Contains(printables, b):
return gs, gs.parser.print()
case sliceContains(executors, b):
case slices.Contains(executors, b):
return gs, gs.parser.execute()
}
+4 -4
View File
@@ -20,12 +20,12 @@ type AnsiParser struct {
oscString state
stateMap []state
logf func(string, ...interface{})
logf func(string, ...any)
}
type Option func(*AnsiParser)
func WithLogf(f func(string, ...interface{})) Option {
func WithLogf(f func(string, ...any)) Option {
return func(ap *AnsiParser) {
ap.logf = f
}
@@ -45,7 +45,7 @@ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Opti
logger := log.New(logFile, "", log.LstdFlags)
if ap.logf != nil {
l := ap.logf
ap.logf = func(s string, v ...interface{}) {
ap.logf = func(s string, v ...any) {
l(s, v...)
logger.Printf(s, v...)
}
@@ -55,7 +55,7 @@ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Opti
}
if ap.logf == nil {
ap.logf = func(string, ...interface{}) {}
ap.logf = func(string, ...any) {}
}
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 {
remaining := minCount - len(ints)
for i := 0; i < remaining; i++ {
for range remaining {
ints = append(ints, dflt)
}
}
+4 -2
View File
@@ -1,5 +1,7 @@
package ansiterm
import "slices"
type state interface {
Enter() error
Exit() error
@@ -32,7 +34,7 @@ func (base baseState) Handle(b byte) (s state, e error) {
return base.parser.escape, nil
case b == OSC_STRING:
return base.parser.oscString, nil
case sliceContains(toGroundBytes, b):
case slices.Contains(toGroundBytes, b):
return base.parser.ground, nil
}
@@ -52,7 +54,7 @@ func (base baseState) Transition(s state) error {
execBytes = append(execBytes, 0x99)
execBytes = append(execBytes, 0x9A)
if sliceContains(execBytes, base.parser.context.currentChar) {
if slices.Contains(execBytes, base.parser.context.currentChar) {
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
+96 -90
View File
@@ -1,14 +1,17 @@
// +build windows
//go:build windows
package winterm
import (
"fmt"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
//===========================================================================================================
// ===========================================================================================================
// IMPORTANT NOTE:
//
// 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
//
// See http://golang.org/doc/go1.3.
//===========================================================================================================
// ===========================================================================================================
var (
kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
kernel32DLL = windows.NewLazyDLL("kernel32.dll")
getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo")
setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo")
setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition")
setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA")
setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo")
writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW")
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 (
// Console modes
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080
ENABLE_AUTO_POSITION = 0x0100
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
ENABLE_PROCESSED_INPUT = windows.ENABLE_PROCESSED_INPUT
ENABLE_LINE_INPUT = windows.ENABLE_LINE_INPUT
ENABLE_ECHO_INPUT = windows.ENABLE_ECHO_INPUT
ENABLE_WINDOW_INPUT = windows.ENABLE_WINDOW_INPUT
ENABLE_MOUSE_INPUT = windows.ENABLE_MOUSE_INPUT
ENABLE_INSERT_MODE = windows.ENABLE_INSERT_MODE
ENABLE_QUICK_EDIT_MODE = windows.ENABLE_QUICK_EDIT_MODE
ENABLE_EXTENDED_FLAGS = windows.ENABLE_EXTENDED_FLAGS
ENABLE_AUTO_POSITION = windows.ENABLE_AUTO_POSITION
ENABLE_VIRTUAL_TERMINAL_INPUT = windows.ENABLE_VIRTUAL_TERMINAL_INPUT
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
DISABLE_NEWLINE_AUTO_RETURN = 0x0008
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
ENABLE_PROCESSED_OUTPUT = windows.ENABLE_PROCESSED_OUTPUT
ENABLE_WRAP_AT_EOL_OUTPUT = windows.ENABLE_WRAP_AT_EOL_OUTPUT
ENABLE_VIRTUAL_TERMINAL_PROCESSING = windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
DISABLE_NEWLINE_AUTO_RETURN = windows.DISABLE_NEWLINE_AUTO_RETURN
ENABLE_LVB_GRID_WORLDWIDE = windows.ENABLE_LVB_GRID_WORLDWIDE
)
// Character attributes
// Note:
// -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan).
// Clearing all foreground or background colors results in black; setting all creates white.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes.
// Character attributes
//
// Foreground and background attributes can be combined to produce colors.
// Clearing all foreground or background color bits produces black; setting
// all color bits produces white.
//
// See https://learn.microsoft.com/windows/console/char-info-str.
const (
FOREGROUND_BLUE uint16 = 0x0001
FOREGROUND_GREEN uint16 = 0x0002
FOREGROUND_RED uint16 = 0x0004
@@ -86,23 +88,29 @@ const (
COMMON_LVB_MASK uint16 = 0xFF00
COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000
COMMON_LVB_UNDERSCORE uint16 = 0x8000
)
// Input event types
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
KEY_EVENT = 0x0001
MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004
MENU_EVENT = 0x0008
FOCUS_EVENT = 0x0010
// Input event types
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
const (
KEY_EVENT = windows.KEY_EVENT
MOUSE_EVENT = windows.MOUSE_EVENT
WINDOW_BUFFER_SIZE_EVENT = windows.WINDOW_BUFFER_SIZE_EVENT
MENU_EVENT = windows.MENU_EVENT
FOCUS_EVENT = windows.FOCUS_EVENT
)
// WaitForSingleObject return codes
WAIT_ABANDONED = 0x00000080
WAIT_FAILED = 0xFFFFFFFF
WAIT_SIGNALED = 0x0000000
WAIT_TIMEOUT = 0x00000102
// WaitForSingleObject return codes.
const (
WAIT_ABANDONED = windows.WAIT_ABANDONED
WAIT_FAILED = windows.WAIT_FAILED
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
WAIT_INFINITE = 0xFFFFFFFF
// WaitForSingleObject wait durations.
const (
WAIT_INFINITE = windows.INFINITE
WAIT_ONE_SECOND = 1000
WAIT_HALF_SECOND = 500
WAIT_QUARTER_SECOND = 250
@@ -122,6 +130,8 @@ type (
Visible int32
}
// CONSOLE_SCREEN_BUFFER_INFO is identical to [windows.ConsoleScreenBufferInfo]
// but implements [fmt.Stringer].
CONSOLE_SCREEN_BUFFER_INFO struct {
Size COORD
CursorPosition COORD
@@ -130,17 +140,11 @@ type (
MaximumWindowSize COORD
}
COORD struct {
X int16
Y int16
}
// COORD is identical to [windows.Coord] but implements [fmt.Stringer].
COORD windows.Coord
SMALL_RECT struct {
Left int16
Top int16
Right int16
Bottom int16
}
// SMALL_RECT is identical to [windows.SmallRect] but implements [fmt.Stringer].
SMALL_RECT windows.SmallRect
// 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.
@@ -189,43 +193,45 @@ func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error
// SetConsoleCursorPosition location of the console cursor.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx.
func SetConsoleCursorPosition(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord))
use(coord)
return checkError(r1, r2, err)
return windows.SetConsoleCursorPosition(windows.Handle(handle), windows.Coord(coord))
}
// 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.
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
}
// 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.
func SetConsoleMode(handle uintptr, mode uint32) error {
r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0)
use(mode)
return checkError(r1, r2, err)
return windows.SetConsoleMode(windows.Handle(handle), mode)
}
// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx.
func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
info := CONSOLE_SCREEN_BUFFER_INFO{}
err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0))
if err != nil {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(handle), &info); err != nil {
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 {
r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char)))
use(scrollRect)
use(clipRect)
use(destOrigin)
use(char)
runtime.KeepAlive(scrollRect)
runtime.KeepAlive(clipRect)
runtime.KeepAlive(destOrigin)
runtime.KeepAlive(char)
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.
func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord))
use(coord)
runtime.KeepAlive(coord)
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.
func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
use(attribute)
runtime.KeepAlive(attribute)
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.
func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error {
r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect)))
use(isAbsolute)
use(rect)
runtime.KeepAlive(isAbsolute)
runtime.KeepAlive(rect)
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.
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)))
use(buffer)
use(bufferSize)
use(bufferCoord)
runtime.KeepAlive(buffer)
runtime.KeepAlive(bufferSize)
runtime.KeepAlive(bufferCoord)
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.
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)))
use(buffer)
runtime.KeepAlive(buffer)
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.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx.
func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) {
r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait)))
switch r1 {
case WAIT_ABANDONED, WAIT_TIMEOUT:
event, err := windows.WaitForSingleObject(windows.Handle(handle), msWait)
if err != nil {
return false, err
}
switch event {
case windows.WAIT_ABANDONED, uint32(windows.WAIT_TIMEOUT):
return false, nil
case WAIT_SIGNALED:
case windows.WAIT_OBJECT_0:
return true, nil
default:
return false, nil
}
use(msWait)
return false, err
}
// 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.
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
+11 -33
View File
@@ -1,10 +1,12 @@
// +build windows
//go:build windows
package winterm
const (
horizontal = iota
vertical
line
column
)
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)
case vertical:
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 err
}
return nil
return h.setCursorPosition(position, h.getCursorWindow(info))
}
func (h *windowsAnsiEventHandler) moveCursorLine(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
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
return h.moveCursor(line, param)
}
func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error {
info, err := GetConsoleScreenBufferInfo(h.fd)
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
return h.moveCursor(column, param)
}
+3 -13
View File
@@ -1,4 +1,4 @@
// +build windows
//go:build windows
package winterm
@@ -50,12 +50,7 @@ func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD,
coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yEnd
err = h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
return nil
return h.clearRect(attributes, coordStart, coordEnd)
}
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
}
err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
if err != nil {
return err
}
return nil
return WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
}
+4 -11
View File
@@ -1,4 +1,4 @@
// +build windows
//go:build windows
package winterm
@@ -39,9 +39,8 @@ func (h *windowsAnsiEventHandler) deleteLines(param int) error {
if start >= sr.top && start <= sr.bottom {
sr.top = start
return h.scroll(param, sr, info)
} else {
return nil
}
return nil
}
func (h *windowsAnsiEventHandler) insertLines(param int) error {
@@ -72,10 +71,7 @@ func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSO
Attributes: h.attributes,
}
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
}
func (h *windowsAnsiEventHandler) deleteCharacters(param int) error {
@@ -111,8 +107,5 @@ func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *
Attributes: h.attributes,
}
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build windows
//go:build windows
package winterm
+19 -33
View File
@@ -1,4 +1,4 @@
// +build windows
//go:build windows
package winterm
@@ -169,9 +169,7 @@ func (h *windowsAnsiEventHandler) executeLF() error {
return err
}
h.logf("Resetting cursor position for LF without CR")
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
return SetConsoleCursorPosition(h.fd, pos)
}
}
return nil
@@ -373,7 +371,7 @@ func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
}
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)
}
@@ -423,7 +421,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
targetWidth = 132
}
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)
return err
}
@@ -436,12 +434,12 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
return err
}
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)
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 {
@@ -468,15 +466,15 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
switch param {
case 0:
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:
start = COORD{0, 0}
start = COORD{X: 0, Y: 0}
end = info.CursorPosition
case 2:
start = COORD{0, 0}
end = COORD{info.Size.X - 1, info.Size.Y - 1}
start = COORD{X: 0, Y: 0}
end = COORD{X: info.Size.X - 1, Y: info.Size.Y - 1}
}
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 {
return err
}
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
return err
}
return SetConsoleWindowInfo(h.fd, true, window)
}
return nil
@@ -525,23 +521,18 @@ func (h *windowsAnsiEventHandler) EL(param int) error {
switch param {
case 0:
start = info.CursorPosition
end = COORD{info.Size.X, info.CursorPosition.Y}
end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
case 1:
start = COORD{0, info.CursorPosition.Y}
start = COORD{X: 0, Y: info.CursorPosition.Y}
end = info.CursorPosition
case 2:
start = COORD{0, info.CursorPosition.Y}
end = COORD{info.Size.X, info.CursorPosition.Y}
start = COORD{X: 0, Y: info.CursorPosition.Y}
end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
}
err = h.clearRange(h.attributes, start, end)
if err != nil {
return err
}
return nil
return h.clearRange(h.attributes, start, end)
}
func (h *windowsAnsiEventHandler) IL(param int) error {
@@ -611,12 +602,7 @@ func (h *windowsAnsiEventHandler) SGR(params []int) error {
if h.inverted {
attributes = invertAttributes(attributes)
}
err := SetConsoleTextAttribute(h.fd, attributes)
if err != nil {
return err
}
return nil
return SetConsoleTextAttribute(h.fd, attributes)
}
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}}
size := COORD{1, 1}
position := COORD{0, 0}
size := COORD{X: 1, Y: 1}
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}
if err := WriteConsoleOutput(h.fd, charInfo, size, position, &region); err != nil {
return err
+33 -3
View File
@@ -408,7 +408,10 @@ func (ctx *genericEncrypter) EncryptWithAuthData(plaintext, aad []byte) (*JSONWe
(*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)
if err != nil {
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
// function does not support multi-recipient. If you desire multi-recipient
// decryption use DecryptMulti instead.
@@ -485,7 +495,10 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
tag: obj.tag,
}
authData := obj.computeAuthData()
authData, err := obj.computeAuthData()
if err != nil {
return nil, err
}
var plaintext []byte
recipient := obj.recipients[0]
@@ -495,6 +508,10 @@ func (obj JSONWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)
if err != nil {
return nil, ErrCryptoFailure
}
err = validateContentEncryptionKeySize(cek, cipher)
if err != nil {
return nil, ErrCryptoFailure
}
// Found a valid CEK -- let's try to decrypt.
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
// 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) {
globalHeaders := obj.mergedHeaders(nil)
@@ -553,7 +576,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
tag: obj.tag,
}
authData := obj.computeAuthData()
authData, err := obj.computeAuthData()
if err != nil {
return -1, Header{}, nil, err
}
index := -1
var plaintext []byte
@@ -572,6 +598,10 @@ func (obj JSONWebEncryption) DecryptMulti(decryptionKey interface{}) (int, Heade
if err != nil {
continue
}
err = validateContentEncryptionKeySize(cek, cipher)
if err != nil {
continue
}
// Found a valid CEK -- let's try to decrypt.
plaintext, err = cipher.decrypt(cek, authData, parts)
+6 -32
View File
@@ -30,30 +30,6 @@ import (
"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
func stripWhitespace(data string) string {
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.
//
// A nil byteBuffer represents an empty slice of bytes.
type byteBuffer struct {
data []byte
}
@@ -169,13 +147,13 @@ func (b *byteBuffer) UnmarshalJSON(data []byte) error {
return err
}
*b = *newBuffer(decoded)
b.data = decoded
return nil
}
func (b *byteBuffer) base64() string {
return base64.RawURLEncoding.EncodeToString(b.data)
return base64.RawURLEncoding.EncodeToString(b.bytes())
}
func (b *byteBuffer) bytes() []byte {
@@ -186,12 +164,8 @@ func (b *byteBuffer) bytes() []byte {
return b.data
}
func (b byteBuffer) bigInt() *big.Int {
return new(big.Int).SetBytes(b.data)
}
func (b byteBuffer) toInt() int {
return int(b.bigInt().Int64())
func (b *byteBuffer) bigInt() *big.Int {
return new(big.Int).SetBytes(b.bytes())
}
func base64EncodeLen(sl []byte) int {
+13
View File
@@ -671,6 +671,19 @@ func (d *decodeState) object(v reflect.Value) {
for _, i := range f.index {
if subv.Kind() == reflect.Ptr {
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 = subv.Elem()
+13 -1
View File
@@ -1025,7 +1025,19 @@ func typeFields(t reflect.Type) []field {
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); 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
}
tag := sf.Tag.Get("json")
+59 -25
View File
@@ -25,6 +25,12 @@ import (
"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.
type rawJSONWebEncryption struct {
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.
func (obj JSONWebEncryption) computeAuthData() []byte {
func (obj JSONWebEncryption) computeAuthData() ([]byte, error) {
var protected string
switch {
case obj.original != nil && obj.original.Protected != nil:
protected = obj.original.Protected.base64()
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:
protected = ""
}
@@ -102,7 +112,7 @@ func (obj JSONWebEncryption) computeAuthData() []byte {
output = append(output, []byte(base64.RawURLEncoding.EncodeToString(obj.aad))...)
}
return output
return output, nil
}
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.2
//
// The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" 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 keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be non-empty. Non-matching algorithms cause a parse error.
//
// Deprecated: use ParseEncryptedJSON or ParseEncryptedCompact depending on which serialization you expect.
func ParseEncrypted(input string,
keyEncryptionAlgorithms []KeyAlgorithm,
contentEncryption []ContentEncryption,
@@ -145,9 +154,13 @@ func ParseEncrypted(input string,
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
//
// 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(
input string,
keyEncryptionAlgorithms []KeyAlgorithm,
@@ -177,6 +190,9 @@ func (parsed *rawJSONWebEncryption) sanitized(
if len(contentEncryption) == 0 {
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{
original: parsed,
@@ -195,21 +211,11 @@ func (parsed *rawJSONWebEncryption) sanitized(
}
}
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
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()
protected, err := parseProtectedHeader(parsed.Protected)
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 {
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.ciphertext = parsed.Ciphertext.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.
//
// 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(
input string,
keyAlgorithms []KeyAlgorithm,
@@ -354,7 +371,10 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
return "", ErrNotSupported
}
serializedProtected := mustSerializeJSON(obj.protected)
serializedProtected, err := json.Marshal(obj.protected)
if err != nil {
return "", err
}
return base64JoinWithDots(
serializedProtected,
@@ -366,7 +386,13 @@ func (obj JSONWebEncryption) CompactSerialize() (string, error) {
}
// 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 {
if len(obj.recipients) == 0 {
return ""
}
raw := rawJSONWebEncryption{
Unprotected: obj.unprotected,
Iv: newBuffer(obj.iv),
@@ -392,8 +418,16 @@ func (obj JSONWebEncryption) FullSerialize() string {
}
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"
"errors"
"fmt"
"math"
"math/big"
"net/url"
"reflect"
@@ -177,13 +178,29 @@ func (k JSONWebKey) MarshalJSON() ([]byte, error) {
// UnmarshalJSON reads a key from its JSON representation.
//
// 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
err = json.Unmarshal(data, &raw)
if err != nil {
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)
if err != nil {
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
}
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")
}
key, err = raw.symmetricKey()
@@ -272,10 +289,8 @@ func (k *JSONWebKey) UnmarshalJSON(data []byte) (err error) {
return ErrUnsupportedKeyType
}
if certPub != nil && keyPub != nil {
if !reflect.DeepEqual(certPub, keyPub) {
return errors.New("go-jose/go-jose: invalid JWK, public keys in key and x5c fields do not match")
}
if len(certs) > 0 && (certPub == nil || !reflect.DeepEqual(certPub, keyPub)) {
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}
@@ -392,6 +407,9 @@ func ecThumbprintInput(curve elliptic.Curve, x, y *big.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,
newBufferFromInt(uint64(e)).base64(),
newBuffer(n.Bytes()).base64()), nil
@@ -505,14 +523,41 @@ func (k *JSONWebKey) Valid() bool {
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) {
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")
}
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{
N: key.N.bigInt(),
E: key.E.toInt(),
N: n,
E: int(eInt64),
}, 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 curve specified in the "crv" parameter.
// 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")
}
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")
}
@@ -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, ", "))
}
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{
PublicKey: rsa.PublicKey{
N: key.N.bigInt(),
E: key.E.toInt(),
},
D: key.D.bigInt(),
Primes: []*big.Int{
key.P.bigInt(),
key.Q.bigInt(),
},
PublicKey: *pubKey,
D: key.D.bigInt(),
Primes: []*big.Int{p, q},
}
if key.Dp != nil {
@@ -695,7 +745,7 @@ func (key rawJSONWebKey) rsaPrivateKey() (*rsa.PrivateKey, error) {
rv.Precomputed.Qinv = key.Qi.bigInt()
}
err := rv.Validate()
err = rv.Validate()
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 curve specified in the "crv" parameter.
// 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")
}
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")
}
// 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")
}
+79 -32
View File
@@ -27,6 +27,12 @@ import (
"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.
type rawJSONWebSignature struct {
Payload *byteBuffer `json:"payload,omitempty"`
@@ -86,6 +92,11 @@ type Signature struct {
// Verify() after parsing to validate the signature and obtain the payload.
//
// 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(
signature string,
signatureAlgorithms []SignatureAlgorithm,
@@ -108,6 +119,9 @@ func ParseSigned(
// Verify() after parsing to validate the signature and obtain the payload.
//
// 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(
signature string,
signatureAlgorithms []SignatureAlgorithm,
@@ -125,6 +139,9 @@ func ParseSignedCompact(
// parsing. Call Verify() after parsing to validate the signature and obtain the payload.
//
// 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(
signature string,
payload []byte,
@@ -157,7 +174,11 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
authData.WriteString(signature.original.Protected.base64())
} else if signature.protected != nil {
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
@@ -180,9 +201,13 @@ func (obj JSONWebSignature) computeAuthData(payload []byte, signature *Signature
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
//
// 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(
input string,
signatureAlgorithms []SignatureAlgorithm,
@@ -236,6 +261,9 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
if parsed.Payload == nil {
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{
payload: parsed.Payload.bytes(),
@@ -245,14 +273,13 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
if len(parsed.Signatures) == 0 {
// No signatures array, must be flattened serialization
signature := Signature{}
if parsed.Protected != nil && len(parsed.Protected.bytes()) > 0 {
signature.protected = &rawHeader{}
err := json.Unmarshal(parsed.Protected.bytes(), signature.protected)
if err != nil {
return nil, err
}
prot, err := parseProtectedHeader(parsed.Protected)
if err != nil {
return nil, err
}
signature.protected = prot
// Check that there is not a nonce in the unprotected header
if parsed.Header != nil && parsed.Header.getNonce() != "" {
return nil, ErrUnprotectedNonce
@@ -275,17 +302,17 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
Signature: parsed.Signature,
}
var err error
signature.Header, err = signature.mergedHeaders().sanitized()
if err != nil {
return nil, err
}
alg := SignatureAlgorithm(signature.Header.Algorithm)
mergedHeaders := signature.mergedHeaders()
alg := mergedHeaders.getSignatureAlgorithm()
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
}
signature.Header, err = mergedHeaders.sanitized()
if err != nil {
return nil, err
}
if signature.header != nil {
signature.Unprotected, err = signature.header.sanitized()
if err != nil {
@@ -310,30 +337,31 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
}
for i, sig := range parsed.Signatures {
if sig.Protected != nil && len(sig.Protected.bytes()) > 0 {
obj.Signatures[i].protected = &rawHeader{}
err := json.Unmarshal(sig.Protected.bytes(), obj.Signatures[i].protected)
if err != nil {
return nil, err
}
prot, err := parseProtectedHeader(sig.Protected)
if err != nil {
return nil, err
}
obj.Signatures[i].protected = prot
// Check that there is not a nonce in the unprotected header
if sig.Header != nil && sig.Header.getNonce() != "" {
return nil, ErrUnprotectedNonce
}
var err error
obj.Signatures[i].Header, err = obj.Signatures[i].mergedHeaders().sanitized()
if err != nil {
return nil, err
}
obj.Signatures[i].header = sig.Header
alg := SignatureAlgorithm(obj.Signatures[i].Header.Algorithm)
mergedHeaders := obj.Signatures[i].mergedHeaders()
alg := mergedHeaders.getSignatureAlgorithm()
if !containsSignatureAlgorithm(signatureAlgorithms, alg) {
return nil, newErrUnexpectedSignatureAlgorithm(alg, signatureAlgorithms)
}
obj.Signatures[i].Header, err = mergedHeaders.sanitized()
if err != nil {
return nil, err
}
if obj.Signatures[i].header != nil {
obj.Signatures[i].Unprotected, err = obj.Signatures[i].header.sanitized()
if err != nil {
@@ -359,7 +387,6 @@ func (parsed *rawJSONWebSignature) sanitized(signatureAlgorithms []SignatureAlgo
// Copy value of sig
original := sig
obj.Signatures[i].header = sig.Header
obj.Signatures[i].original = &original
}
@@ -424,7 +451,10 @@ func (obj JSONWebSignature) compactSerialize(detached bool) (string, error) {
return "", ErrNotSupported
}
serializedProtected := mustSerializeJSON(obj.Signatures[0].protected)
serializedProtected, err := json.Marshal(obj.Signatures[0].protected)
if err != nil {
return "", err
}
var payload []byte
if !detached {
@@ -449,14 +479,23 @@ func (obj JSONWebSignature) DetachedCompactSerialize() (string, error) {
}
// FullSerialize serializes an object using the full JSON serialization format.
//
// It returns "" if obj cannot be serialized.
func (obj JSONWebSignature) FullSerialize() string {
raw := rawJSONWebSignature{
Payload: newBuffer(obj.payload),
}
if len(obj.Signatures) == 0 {
return ""
}
if len(obj.Signatures) == 1 {
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.Header = obj.Signatures[0].header
@@ -470,10 +509,18 @@ func (obj JSONWebSignature) FullSerialize() string {
}
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)")
// 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.
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
}
// 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) {
sig, err := jose.ParseSignedCompact(s, signatureAlgorithms)
if err != nil {
@@ -142,13 +147,10 @@ func parseEncryptedCompact(
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"
// header parameters respectively. They must be nonempty, and each "alg" or "enc" 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 keyAlgorithms and contentEncryption parameters contain the allowable algorithms in the "alg" and "enc"
// header parameters respectively. They must be non-empty. Non-matching algorithms cause a parse error.
func ParseEncrypted(s string,
keyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption,
@@ -164,17 +166,10 @@ func ParseEncrypted(s string,
}, 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"
// header parameters, respectively, of the outer JWE. They must be nonempty, and each "alg" or "enc"
// 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.
// The encryptionKeyAlgorithms, contentEncryption, and signatureAlgorithms parameters contain the allowable
// algorithms. They must be non-empty. Non-matching algorithms cause a parse error.
func ParseSignedAndEncrypted(s string,
encryptionKeyAlgorithms []jose.KeyAlgorithm,
contentEncryption []jose.ContentEncryption,
+43 -37
View File
@@ -18,6 +18,7 @@ package jose
import (
"crypto/elliptic"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"errors"
@@ -210,13 +211,20 @@ type Header struct {
// Certificates verifies & returns the certificate chain present
// 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.
func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
if len(h.certificates) == 0 {
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]
if opts.Intermediates == nil {
opts.Intermediates = x509.NewCertPool()
@@ -297,9 +305,10 @@ func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
if v == nil {
return nil, nil
}
var epk *JSONWebKey
err := json.Unmarshal(*v, &epk)
if err != nil {
// RFC 7518 Section 4.6.1.1: the "epk" header is the ephemeral public key
// of the originator. Reject private key material before parsing it.
epk := new(JSONWebKey)
if err := epk.unmarshalJSON(*v, false); err != nil {
return nil, err
}
return epk, nil
@@ -325,20 +334,6 @@ func (parsed rawHeader) getTag() (*byteBuffer, error) {
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
// returns an empty slice.
func (parsed rawHeader) getCritical() ([]string, error) {
@@ -424,10 +419,14 @@ func (parsed rawHeader) sanitized() (h Header, err error) {
}
switch k {
case headerJWK:
var jwk *JSONWebKey
err = json.Unmarshal(*v, &jwk)
// RFC 7515 Section 4.1.3 and RFC 7516 Section 4.1.5: the "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 {
err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v))
err = fmt.Errorf("failed to unmarshal JWK: %w", err)
return
}
h.JSONWebKey = jwk
@@ -499,22 +498,8 @@ func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
}
func (parsed rawHeader) isSet(k HeaderKey) bool {
dvr := parsed[k]
if dvr == nil {
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
_, ok := parsed[k]
return ok
}
// 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)
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
}
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
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 {
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")
}
+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 {
total += int(v)
} else {
total -= int(v)
// -1 takes one cell. Adding -v would let a wrapped -32768 pass.
total++
}
}
defer func() {
+6
View File
@@ -3,6 +3,7 @@ package fse
import (
"errors"
"fmt"
"math"
)
const (
@@ -123,6 +124,11 @@ func (s *Scratch) readNCount() error {
remaining -= 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)
charnum++
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) {
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
s.fse.DecompressLimit = 255
hw := s.huffWeight[:]
+3
View File
@@ -219,6 +219,9 @@ func BuildDict(o BuildDictOptions) ([]byte, error) {
if len(contents) == 0 {
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{
id: o.ID,
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.
// However, it provides really fast recompression of Snappy streams.
// 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 {
r io.Reader
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
}
// 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 */ {
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.DNSNames = slices.Clone(es.DNSNames)
epCopy.DriverOpts = maps.Clone(es.DriverOpts)
epCopy.MacAddress = slices.Clone(es.MacAddress)
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.
//
// 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
// 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)
default:
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)
}
+3 -1
View File
@@ -100,8 +100,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (retConn net
if err != nil {
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 {
_ = resp.Body.Close()
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_outer_classname: "TimestampProto"
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
objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -53,7 +53,7 @@ file {
java_package: "com.google.protobuf"
java_outer_classname: "DurationProto"
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
objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -157,7 +157,7 @@ file {
java_package: "com.google.protobuf"
java_outer_classname: "WrappersProto"
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
objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes"
@@ -484,6 +484,13 @@ file {
type_name: ".google.protobuf.FieldOptions"
json_name: "options"
}
field {
name: "proto3_optional"
number: 17
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "proto3Optional"
}
enum_type {
name: "Type"
value {
@@ -853,7 +860,7 @@ file {
number: 31
label: LABEL_OPTIONAL
type: TYPE_BOOL
default_value: "false"
default_value: "true"
json_name: "ccEnableArenas"
}
field {
@@ -1405,7 +1412,7 @@ file {
java_package: "com.google.protobuf"
java_outer_classname: "DescriptorProtos"
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
objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.Reflection"
@@ -5208,7 +5215,7 @@ file {
java_package: "com.google.protobuf"
java_outer_classname: "AnyProto"
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"
csharp_namespace: "Google.Protobuf.WellKnownTypes"
}
@@ -10590,7 +10597,7 @@ file {
syntax: "proto3"
}
file {
name: "go.etcd.io/etcd/raft/v3/raftpb/raft.proto"
name: "go.etcd.io/raft/v3/raftpb/raft.proto"
package: "raftpb"
dependency: "gogoproto/gogo.proto"
message_type {
@@ -10773,6 +10780,16 @@ file {
}
json_name: "commit"
}
field {
name: "vote"
number: 13
label: LABEL_OPTIONAL
type: TYPE_UINT64
options {
65001: 0
}
json_name: "vote"
}
field {
name: "snapshot"
number: 9
@@ -10780,7 +10797,7 @@ file {
type: TYPE_MESSAGE
type_name: ".raftpb.Snapshot"
options {
65001: 0
65001: 1
}
json_name: "snapshot"
}
@@ -10809,8 +10826,22 @@ file {
number: 12
label: LABEL_OPTIONAL
type: TYPE_BYTES
options {
65001: 1
}
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 {
name: "HardState"
@@ -11079,6 +11110,26 @@ file {
name: "MsgPreVoteResp"
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 {
name: "ConfChangeTransition"
@@ -11130,7 +11181,7 @@ file {
package: "docker.swarmkit.v1"
dependency: "github.com/docker/swarmkit/api/objects.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: "github.com/docker/swarmkit/protobuf/plugin/plugin.proto"
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.
//
// 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.
@@ -24,7 +24,7 @@ type CopierFrom interface {
//
// If the copy cannot be performed, this function will panic. Make sure to test
// types that use this function.
func Copy(dst, src interface{}) {
func Copy(dst, src any) {
switch dst := dst.(type) {
case *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
}
func fromArgs(args ...interface{}) ([]byte, error) {
func fromArgs(args ...any) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
@@ -86,7 +86,7 @@ func fromArgs(args ...interface{}) ([]byte, error) {
return []byte(arg), nil
}
func prefixFromArgs(args ...interface{}) ([]byte, error) {
func prefixFromArgs(args ...any) ([]byte, error) {
val, err := fromArgs(args...)
if err != nil {
return nil, err
+16
View File
@@ -5,6 +5,21 @@ from https://github.com/syndtr/gocapability/commit/42c35b4376354fd5.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.5.0] - 2026-10-23
### Breaking changes
* Go 1.24 or later is now required. (#264)
### Fixed
* [LastCap] no longer reads `/proc/sys/kernel/cap_last_cap`, querying the
kernel via `prctl(PR_CAPBSET_READ)` instead. This makes the package work
when `/proc` is not mounted, and fixes a possible panic or infinite loop
when `/proc/sys/kernel/cap_last_cap` contains a bogus value (for example,
if something is mounted over `/proc`). (#265, #269)
### Changed
* Minor code cleanups. (#187)
## [0.4.0] - 2024-11-11
### Added
@@ -104,6 +119,7 @@ This is an initial release since the fork.
[SetAmbient]: https://pkg.go.dev/github.com/moby/sys/capability#SetAmbient
<!-- Minor releases. -->
[0.5.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.5.0
[0.4.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.4.0
[0.3.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.3.0
[0.2.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.2.0
+65 -17
View File
@@ -13,7 +13,6 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"syscall"
@@ -25,27 +24,76 @@ const (
linuxCapVer3 = 0x20080522
)
// capValid reports whether the running kernel supports capability c.
func capValid(c Cap) (bool, error) {
err := prctl(syscall.PR_CAPBSET_READ, uintptr(c), 0)
if errors.Is(err, syscall.EINVAL) {
return false, nil
}
return err == nil, err
}
// lastCap returns the highest capability supported by the running kernel.
var lastCap = sync.OnceValues(func() (Cap, error) {
f, err := os.Open("/proc/sys/kernel/cap_last_cap")
last, err := findLastCap()
if err != nil {
return 0, err
return 0, fmt.Errorf("unable to get last capability: %w", err)
}
buf := make([]byte, 11)
l, err := f.Read(buf)
f.Close()
if err != nil {
return 0, err
}
buf = buf[:l]
last, err := strconv.Atoi(strings.TrimSpace(string(buf)))
if err != nil {
return 0, err
}
return Cap(last), nil
return last, nil
})
func findLastCap() (Cap, error) {
// Based on the fact Go 1.24+ supports Linux >= 3.2, and
// - CAP_WAKE_ALARM (35) was added in 3.0;
// - CAP_CHECKPOINT_RESTORE (40) was added in 5.9, and it is
// the last added capability as of October 2026 (Linux 7.3);
//
// the last capability is at least minLastCap, and most probably
// lastKnownCap (but newer kernels may have more).
//
// maxLastCap is the highest capability which can be represented
// by the kernel capability ABI v3 (two 32-bit words per set).
const (
minLastCap = CAP_WAKE_ALARM
lastKnownCap = CAP_CHECKPOINT_RESTORE
maxLastCap = Cap(63)
)
// Start from lastKnownCap, and go up if it's valid, or down if it's
// not. For most kernels, this takes two syscalls.
c := lastKnownCap
ok, err := capValid(c)
if err != nil {
return 0, err
}
if ok {
// Go up while the next one is valid.
for c < maxLastCap {
ok, err := capValid(c + 1)
if err != nil {
return 0, err
}
if !ok {
break
}
c++
}
return c, nil
}
// Go down until a valid one is found.
for c > minLastCap {
c--
ok, err := capValid(c)
if err != nil {
return 0, err
}
if ok {
return c, nil
}
}
return 0, fmt.Errorf("PR_CAPBSET_READ returned EINVAL for %s", minLastCap)
}
func capUpperMask() uint32 {
last, err := lastCap()
if err != nil || last < 32 {
+4 -3
View File
@@ -141,16 +141,17 @@ func setVfsCap(path string, data *vfscapData) (err error) {
return
}
var size uintptr
if data.version == 1 {
switch data.version {
case 1:
data.magic = vfsCapVer1
size = vfscapDataSizeV1
} else if data.version == 2 {
case 2:
data.magic = vfsCapVer2
if data.effective[0] != 0 || data.effective[1] != 0 {
data.magic |= vfsCapFlageffective
}
size = vfscapDataSizeV2
} else {
default:
return syscall.EINVAL
}
_, _, e1 := syscall.RawSyscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0)
@@ -10,12 +10,31 @@ import (
"go.opentelemetry.io/otel/trace"
)
// Attribute keys that can be added to a span.
// Legacy HTTP attribute keys retained for compatibility.
const (
ReadBytesKey = attribute.Key("http.read_bytes") // if anything was read from the request body, the total number of bytes read
ReadErrorKey = attribute.Key("http.read_error") // If an error occurred while reading a request, the string of the error (io.EOF is not recorded)
WroteBytesKey = attribute.Key("http.wrote_bytes") // if anything was written to the response writer, the total number of bytes written
WriteErrorKey = attribute.Key("http.write_error") // if an error occurred while writing a reply, the string of the error (io.EOF is not recorded)
// ReadBytesKey is the attribute key for the number of bytes returned by an
// individual read from an HTTP request body.
//
// Deprecated: there is no direct semantic-convention replacement.
ReadBytesKey = attribute.Key("http.read_bytes")
// ReadErrorKey is the attribute key for the string form of a non-EOF error
// returned while reading an HTTP request body.
//
// Deprecated: there is no direct semantic-convention replacement.
ReadErrorKey = attribute.Key("http.read_error")
// WroteBytesKey is the attribute key for the number of bytes returned by an
// individual write to an HTTP response body.
//
// Deprecated: there is no direct semantic-convention replacement.
WroteBytesKey = attribute.Key("http.wrote_bytes")
// WriteErrorKey is the attribute key for the string form of a non-EOF error
// returned while writing an HTTP response body.
//
// Deprecated: there is no direct semantic-convention replacement.
WriteErrorKey = attribute.Key("http.write_error")
)
// Filter is a predicate used to determine whether a given http.request should
@@ -143,14 +143,15 @@ const (
)
// WithMessageEvents configures the Handler to record the specified events
// (span.AddEvent) on spans. By default only summary attributes are added at the
// end of the request.
// (span.AddEvent) on spans. By default, no read or write events are recorded.
//
// Valid events are:
// - ReadEvents: Record the number of bytes read after every http.Request.Body.Read
// using the ReadBytesKey
// - WriteEvents: Record the number of bytes written after every http.ResponeWriter.Write
// using the WriteBytesKey
// - ReadEvents: Record a "read" span event after every http.Request.Body.Read.
// - WriteEvents: Record a "write" span event after every http.ResponseWriter.Write.
//
// The events do not include per-call byte-count attributes. Total request and
// response body sizes are recorded on the span according to HTTP semantic
// conventions.
func WithMessageEvents(events ...Event) Option {
return optionFunc(func(c *config) {
for _, e := range events {
@@ -129,8 +129,8 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
readRecordFunc := func(int64) {}
if h.readEvent {
readRecordFunc = func(n int64) {
span.AddEvent("read", trace.WithAttributes(ReadBytesKey.Int64(n)))
readRecordFunc = func(int64) {
span.AddEvent("read")
}
}
@@ -150,8 +150,8 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
writeRecordFunc := func(int64) {}
if h.writeEvent {
writeRecordFunc = func(n int64) {
span.AddEvent("write", trace.WithAttributes(WroteBytesKey.Int64(n)))
writeRecordFunc = func(int64) {
span.AddEvent("write")
}
}
@@ -180,12 +180,21 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
if !found {
ctx = ContextWithLabeler(ctx, labeler)
}
rCtx := r.WithContext(ctx)
defer func() {
// Copy MultipartForm back to the original request so net/http can
// find and remove any temp files ParseMultipartForm created on the
// copy. Deferred so the copy-back also runs during panic unwinding,
// letting net/http cleanup paths that still run (HTTP/2 handler
// recovery, outer recovery middleware) find the form.
if rCtx.MultipartForm != nil {
r.MultipartForm = rCtx.MultipartForm
}
}()
next.ServeHTTP(w, rCtx)
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
if r.Pattern != "" {
span.SetName(h.spanNameFormatter(h.operation, r))
if rCtx.Pattern != "" {
span.SetName(h.spanNameFormatter(h.operation, rCtx))
}
statusCode := rww.StatusCode()
@@ -204,9 +213,9 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
ServerName: h.server,
ResponseSize: bytesWritten,
MetricAttributes: semconv.MetricAttributes{
Req: r,
Req: rCtx,
StatusCode: statusCode,
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(r)...),
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(rCtx)...),
},
MetricData: semconv.MetricData{
RequestSize: bytesRead,
@@ -38,11 +38,9 @@ func SplitHostPort(hostport string) (host string, port int) {
host = hostport[1:addrEnd]
return host, port
}
} else {
if i := strings.LastIndexByte(hostport, ':'); i < 0 {
host = hostport
return host, port
}
} else if !strings.Contains(hostport, ":") {
host = hostport
return host, port
}
host, pStr, err := net.SplitHostPort(hostport)
@@ -56,3 +56,27 @@ func LabelerFromContext(ctx context.Context) (*Labeler, bool) {
}
return l, ok
}
// clientLabelerContextKey is a separate context key for the client-side Labeler.
// This prevents server-side Labeler attributes (e.g., http.route) from leaking
// into client-side metrics when a server handler propagates its request context
// into an outbound HTTP client request.
const clientLabelerContextKey labelerContextKeyType = 1
// ContextWithClientLabeler returns a new context with the provided Labeler instance
// for use with client-side HTTP instrumentation (otelhttp.Transport).
// Attributes added to this labeler will be attached to client-side metrics.
func ContextWithClientLabeler(parent context.Context, l *Labeler) context.Context {
return context.WithValue(parent, clientLabelerContextKey, l)
}
// ClientLabelerFromContext retrieves a Labeler instance from the provided context
// for use with client-side HTTP instrumentation. If no Labeler was found, a new,
// empty Labeler is returned and the second return value is false.
func ClientLabelerFromContext(ctx context.Context) (*Labeler, bool) {
l, ok := ctx.Value(clientLabelerContextKey).(*Labeler)
if !ok {
l = &Labeler{}
}
return l, ok
}
@@ -9,6 +9,7 @@ import (
"io"
"net/http"
"net/http/httptrace"
"sync"
"sync/atomic"
"time"
@@ -19,7 +20,6 @@ import (
otelsemconv "go.opentelemetry.io/otel/semconv/v1.43.0"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/request"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconv"
)
@@ -82,6 +82,142 @@ func defaultTransportFormatter(_ string, r *http.Request) string {
return "HTTP " + r.Method
}
// requestTracker tracks the request body lifecycle of a single RoundTrip and
// records the client metrics exactly once, after the request body reaches a
// final state.
//
// A single tracker is allocated per request with a body, replacing the
// body-wrapper allocation of the untracked implementation: the first request
// body is wrapped by the embedded first field, and the lifecycle state is
// held in explicit fields with methods instead of escaping closures. Only
// GetBody retries allocate an additional trackedRequestBody.
type requestTracker struct {
transport *Transport
first trackedRequestBody
originalGetBody func() (io.ReadCloser, error)
// mu protects body, published, and recorded. Body close callbacks may
// fire on a different goroutine (e.g. during transport retries or
// asynchronous closes) while the main goroutine publishes the metric
// data after RoundTrip returns.
mu sync.Mutex
body *trackedRequestBody // Last wrapped request body; nil records no data.
published bool
recorded bool
// Metric data published when RoundTrip returns; immutable afterwards.
ctx context.Context
duration time.Duration
opts semconv.MetricOpts
}
func newRequestTracker(t *Transport, r *http.Request) *requestTracker {
rt := &requestTracker{transport: t}
rt.first = trackedRequestBody{body: r.Body, tracker: rt}
rt.body = &rt.first
r.Body = &rt.first
if r.GetBody != nil {
rt.originalGetBody = r.GetBody
r.GetBody = rt.getBody
}
return rt
}
func (rt *requestTracker) getBody() (io.ReadCloser, error) {
b, err := rt.originalGetBody()
if err != nil {
// The underlying transport will fail to make a retry request,
// hence, record no data.
rt.setBody(nil)
return nil, err
}
if b == nil || b == http.NoBody {
return b, nil
}
tb := &trackedRequestBody{body: b, tracker: rt}
rt.setBody(tb)
return tb, nil
}
func (rt *requestTracker) setBody(b *trackedRequestBody) {
rt.mu.Lock()
rt.body = b
rt.mu.Unlock()
}
// publish stores the metric data gathered when RoundTrip returns and records
// the metrics if the request body already reached a final state.
func (rt *requestTracker) publish(ctx context.Context, d time.Duration, opts semconv.MetricOpts) {
rt.mu.Lock()
rt.ctx = ctx
rt.duration = d
rt.opts = opts
rt.published = true
rt.mu.Unlock()
rt.maybeRecord()
}
// maybeRecord records the client metrics once the metric data has been
// published and the request body has reached a final state. Close is the
// only authoritative completion signal for a non-nil body: a body may yield
// more bytes than its declared ContentLength, so a read count is never proof
// of completion.
func (rt *requestTracker) maybeRecord() {
rt.mu.Lock()
body := rt.body
record := rt.published && !rt.recorded && (body == nil || body.closed.Load())
if record {
rt.recorded = true
}
rt.mu.Unlock()
if !record {
return
}
// The winning caller evaluates the request size here so the recorded
// value reflects the latest byte count.
var requestSize int64
if body != nil {
requestSize = body.read.Load()
}
rt.transport.semconv.RecordMetrics(
rt.ctx,
semconv.MetricData{
RequestSize: requestSize,
RequestDuration: rt.duration,
},
rt.opts,
)
}
// trackedRequestBody wraps a request body to count read bytes and signal the
// tracker when the body is closed.
type trackedRequestBody struct {
body io.ReadCloser
tracker *requestTracker
read atomic.Int64
closed atomic.Bool
}
var _ io.ReadCloser = (*trackedRequestBody)(nil)
func (b *trackedRequestBody) Read(p []byte) (int, error) {
n, err := b.body.Read(p)
b.read.Add(int64(n))
return n, err
}
func (b *trackedRequestBody) Close() error {
// Finalize telemetry before delegating to the underlying Close, which
// may block (mirroring wrappedBody.Close). Otherwise a blocking close
// could suppress client metrics indefinitely.
b.closed.Store(true)
b.tracker.maybeRecord()
return b.body.Close()
}
// RoundTrip creates a Span and propagates its context via the provided request's headers
// before handing the request to the configured base RoundTripper. The created span will
// end when the response body is closed or when a read from the body returns io.EOF.
@@ -110,33 +246,20 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx))
}
labeler, found := LabelerFromContext(ctx)
labeler, found := ClientLabelerFromContext(ctx)
if !found {
ctx = ContextWithLabeler(ctx, labeler)
ctx = ContextWithClientLabeler(ctx, labeler)
}
r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request.
var lastBW *request.BodyWrapper // Records the last body wrapper. Can be nil.
maybeWrapBody := func(body io.ReadCloser) io.ReadCloser {
if body == nil || body == http.NoBody {
return body
}
bw := request.NewBodyWrapper(body, func(int64) {})
lastBW = bw
return bw
}
r.Body = maybeWrapBody(r.Body)
if r.GetBody != nil {
originalGetBody := r.GetBody
r.GetBody = func() (io.ReadCloser, error) {
b, err := originalGetBody()
if err != nil {
lastBW = nil // The underlying transport will fail to make a retry request, hence, record no data.
return nil, err
}
return maybeWrapBody(b), nil
}
// Track the request body lifecycle so metrics report the final read
// size even when the transport keeps reading the body after RoundTrip
// returns. Bodyless requests allocate no tracker and record
// synchronously below.
var tracker *requestTracker
if r.Body != nil && r.Body != http.NoBody {
tracker = newRequestTracker(t, r)
}
span.SetAttributes(t.semconv.RequestTraceAttrs(r)...)
@@ -147,29 +270,32 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
res, err = ensureResponseBody(t.rt, r, res)
}
// Record the metrics on error or no error.
requestDuration := time.Since(requestStartTime)
statusCode := 0
if err == nil {
statusCode = res.StatusCode
}
var requestSize int64
if lastBW != nil {
requestSize = lastBW.BytesRead()
metricOpts := t.semconv.MetricOptions(semconv.MetricAttributes{
Req: r,
Resp: res,
StatusCode: statusCode,
Err: err,
AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
})
if tracker != nil {
// Delay metric recording until the request body reaches a final
// state. The transport can continue reading the body after
// RoundTrip returns, including on errors, since RoundTrippers may
// close the request body asynchronously.
tracker.publish(ctx, requestDuration, metricOpts)
} else {
t.semconv.RecordMetrics(
ctx,
semconv.MetricData{RequestDuration: requestDuration},
metricOpts,
)
}
t.semconv.RecordMetrics(
ctx,
semconv.MetricData{
RequestSize: requestSize,
RequestDuration: time.Since(requestStartTime),
},
t.semconv.MetricOptions(semconv.MetricAttributes{
Req: r,
Resp: res,
StatusCode: statusCode,
Err: err,
AdditionalAttributes: append(labeler.Get(), t.metricAttributesFromRequest(r)...),
}),
)
if err != nil {
span.SetAttributes(otelsemconv.ErrorType(err))
@@ -263,8 +389,7 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
case nil:
// nothing to do here but fall through to the return
case io.EOF:
wb.recordBytesRead()
wb.span.End()
wb.recordMetricsOnce()
default:
wb.span.SetAttributes(otelsemconv.ErrorType(err))
wb.span.SetStatus(codes.Error, err.Error())
@@ -272,21 +397,24 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
return n, err
}
// recordBytesRead is a function that ensures the number of bytes read is recorded once and only once.
func (wb *wrappedBody) recordBytesRead() {
// note: it is more performant (and equally correct) to use atomic.Bool over sync.Once here. In the event that
// two goroutines are racing to call this method, the number of bytes read will no longer increase. Using
// CompareAndSwap allows later goroutines to return quickly and not block waiting for the race winner to finish
// calling wb.record(wb.read.Load()).
// recordMetricsOnce ensures the final number of bytes read is recorded once.
func (wb *wrappedBody) recordMetricsOnce() {
// note: it is more performant (and equally correct) to use atomic.Bool
// over sync.Once here. In the event that two goroutines are racing to
// call this method, the number of bytes read will no longer increase.
// Using CompareAndSwap allows later goroutines to return quickly and not
// block waiting for the race winner to finish calling
// wb.record(wb.read.Load()).
if wb.recorded.CompareAndSwap(false, true) {
// Record the total number of bytes read
wb.record(wb.read.Load())
wb.span.End()
}
}
func (wb *wrappedBody) Close() error {
wb.recordBytesRead()
wb.span.End()
// Finalize telemetry before delegating to the underlying Close, which
// may block (e.g. upgraded streams or custom RoundTripper bodies).
wb.recordMetricsOnce()
if wb.body != nil {
return wb.body.Close()
}
@@ -4,4 +4,4 @@
package otelhttp
// Version is the current release version of the otelhttp instrumentation.
const Version = "0.71.0"
const Version = "0.72.0"
+4 -8
View File
@@ -230,13 +230,6 @@ linters:
- revive
path: schema/v.*/types/.*
text: avoid meaningless package names
# TODO: Having appropriate comments for exported objects helps development,
# even for objects in internal packages. Appropriate comments for all
# exported objects should be added and this exclusion removed.
- linters:
- revive
path: .*internal/.*
text: exported (method|function|type|const) (.+) should have comment or be unexported
# Yes, they are, but it's okay in a test.
- linters:
- revive
@@ -272,7 +265,10 @@ formatters:
- golines
settings:
gofumpt:
extra-rules: true
extra:
group-params: true
clothe-returns: true
balance-calls: true
goimports:
local-prefixes:
- go.opentelemetry.io/otel
+90 -1
View File
@@ -11,6 +11,93 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
<!-- Released section -->
<!-- Don't change this section unless doing release -->
## [1.47.0/0.69.0/0.23.0/0.1.0] - 2026-10-02
This release contains the first stable release of the OpenTelemetry Go Logs API and SDK.
Our project stability guarantees now apply to the following modules:
- `go.opentelemetry.io/otel/log`
- `go.opentelemetry.io/otel/sdk/log`
See our [versioning policy](VERSIONING.md) for more information about these stability guarantees.
### Added
- Add `String` method for `KeyValue` type in `go.opentelemetry.io/otel/attribute`. (#8205)
- Add `String` method for `Set` type in `go.opentelemetry.io/otel/attribute`. (#8347)
- Add `WithMaxExportBatchSize` to `go.opentelemetry.io/otel/sdk/metric` to configure the maximum export batch size for `PeriodicReader`. (#8960)
- Add `WithAttributeValueDepthLimit`, `DefaultAttributeValueDepthLimit`, and `SpanLimits.AttributeValueDepthLimit` in `go.opentelemetry.io/otel/sdk/trace` to configure the maximum depth of span, event, link, and instrumentation scope attribute values. (#8938)
- Add `WithAttributeValueDepthLimit` in `go.opentelemetry.io/otel/sdk/log` to configure the maximum depth of log record and instrumentation scope attribute values. (#8938)
- Add `WithMaxResponseSize` to `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`,
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`, and
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8941)
- Add experimental `ProbabilitySampler` in `go.opentelemetry.io/otel/sdk/trace/x` that conforms to the [OpenTelemetry specification's threshold-based sampling algorithm](https://opentelemetry.io/docs/specs/otel/trace/sdk/#probabilitysampler). (#8123)
- Add experimental `*Binder` extension interfaces in `go.opentelemetry.io/otel/metric/x` for instruments that support binding attributes ahead of time. (#8760)
- Add the experimental `Finisher` synchronous metric instrument extension interface to `go.opentelemetry.io/otel/metric/x`. (#8906)
### Changed
- Use the [OpenTelemetry Attribute Collection representation for non-OTLP protocols](https://opentelemetry.io/docs/specs/otel/common/#attribute-collection-representation-for-non-otlp) for metric data diffs in `go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest`. (#8993)
- Apply a maximum depth of 64 by default to span, event, link, log record, and instrumentation scope attribute values in `go.opentelemetry.io/otel/sdk/trace` and `go.opentelemetry.io/otel/sdk/log`. (#8938)
- Reduce allocations when applying attribute value length limits in `go.opentelemetry.io/otel/sdk/trace` and `go.opentelemetry.io/otel/sdk/log` by rebuilding composite values only when truncation is needed. (#8912)
- Decode `traceparent` using a hex lookup table in `go.opentelemetry.io/otel/propagation`, which rejects the specification-disallowed upper-case characters without a separate scan of the header. (#8739)
- Decode all characters at constant indices in `TraceIDFromHex` and `SpanIDFromHex` in `go.opentelemetry.io/otel/trace` to eliminate bounds checks. (#8740)
### Fixed
- Count valid U+FFFD replacement characters toward attribute value length limits in `go.opentelemetry.io/otel/trace`, `go.opentelemetry.io/otel/sdk/trace`, and `go.opentelemetry.io/otel/sdk/log`.
- Truncate string attribute values to empty strings when the configured length limit is zero, including malformed UTF-8, in `go.opentelemetry.io/otel/trace`, `go.opentelemetry.io/otel/sdk/trace`, and `go.opentelemetry.io/otel/sdk/log`. (#9054)
- Fix a data race in `NewPeriodicReader` where `r.inst` was assigned after the background goroutine was launched in `go.opentelemetry.io/otel/sdk/metric`. (#9028)
- Prevent precision loss for large `int64` values in `Sum`, `Histogram`, and `ExponentialHistogram` aggregations in `go.opentelemetry.io/otel/sdk/metric`. (#8981)
- Ensure `grpc.DialOption` values passed via `WithDialOption` take precedence over conflicting internally-computed defaults in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`,
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`, and
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#8805, #8834, #8836)
- Treat overflowing `OTEL_METRIC_EXPORT_INTERVAL` and `OTEL_METRIC_EXPORT_TIMEOUT` values as invalid in `go.opentelemetry.io/otel/sdk/metric`. (#8800)
- Prevent a panic in `NewFixedSizeReservoir` and `FixedSizeReservoirProvider` when given a negative size in `go.opentelemetry.io/otel/sdk/metric/exemplar`; negative sizes are now clamped to zero, consistent with a size of zero. (#8832)
- Preserve exponential histogram `ZeroThreshold` during OTLP metric export in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#8801)
- Ensure metric helpers in `go.opentelemetry.io/otel/semconv/v1.32.0`, `go.opentelemetry.io/otel/semconv/v1.33.0`, and `go.opentelemetry.io/otel/semconv/v1.34.0` record measurements only once when no attributes are provided. (#8849)
- Treat empty `OTEL_TRACES_SAMPLER` and `OTEL_TRACES_SAMPLER_ARG` values as unset in `go.opentelemetry.io/otel/sdk/trace`. (#8873)
- Normalize global `OTEL_EXPORTER_OTLP_ENDPOINT` path joining in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` so trailing-slash base URLs do not produce double-slash log export paths. (#8864)
- Prevent a deadlock when formatting an error passed to `RecordError` calls back into the span in `go.opentelemetry.io/otel/sdk/trace`. (#8815)
- Prevent `SimpleSpanProcessor.Shutdown` from panicking when constructed with a nil exporter in `go.opentelemetry.io/otel/sdk/trace`. (#8844)
- Propagate invalid exponential histogram scale errors to Prometheus exporter self-observability metrics in `go.opentelemetry.io/otel/exporters/prometheus`. (#8839)
- Retain instrument advisory attributes configured with `go.opentelemetry.io/otel/metric/x.WithDefaultAttributes` when a matching View in `go.opentelemetry.io/otel/sdk/metric` does not specify an attribute filter. (#8859)
- Ignore HTTP URL paths when building OTLP/gRPC metric exporter targets from `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`, while preserving `unix://` and `unix-abstract://` targets; treat `unix-abstract://` endpoints as insecure in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#8862)
- Ignore HTTP(S) paths when deriving gRPC trace exporter endpoints from `OTEL_EXPORTER_OTLP_ENDPOINT` and `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#8852)
- Bound memory used while parsing dense W3C property metadata by storing it compactly and materializing `Property` values on demand in `go.opentelemetry.io/otel/baggage` and `go.opentelemetry.io/otel/propagation`.
### Removed
- Remove the experimental `OTEL_GO_X_METRIC_EXPORT_BATCH_SIZE` environment variable in `go.opentelemetry.io/otel/sdk/metric`.
Use the `WithMaxExportBatchSize` option instead. (#8960)
## [1.47.0-rc.1] - 2026-08-28
This is a release candidate for the v1.47.0 release.
That release is expected to include the `v1` release of the OpenTelemetry Go Logs API and SDK and will provide stability guarantees for the following modules:
- `go.opentelemetry.io/otel/log`
- `go.opentelemetry.io/otel/sdk/log`
See our [versioning policy](VERSIONING.md) for more information about these stability guarantees.
### Added
- Add `Logger`, `GetLoggerProvider`, and `SetLoggerProvider` to `go.opentelemetry.io/otel`. (#8874)
### Deprecated
- Deprecate `go.opentelemetry.io/otel/log/global`; use the equivalent APIs in `go.opentelemetry.io/otel`. (#8874)
### Fixed
- Ignore attempts to unregister unknown span processors in `go.opentelemetry.io/otel/sdk/trace`. (#8840)
### Removed
- Drop support for [Go 1.25]. (#8876)
## [1.46.0/0.68.0/0.22.0/0.0.19] - 2026-08-25
This release is the last to support [Go 1.25].
@@ -3810,7 +3897,9 @@ It contains api and sdk for trace and meter.
- CircleCI build CI manifest files.
- CODEOWNERS file to track owners of this project.
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.46.0...HEAD
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.47.0...HEAD
[1.47.0/0.69.0/0.23.0/0.1.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.47.0
[1.47.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.47.0-rc.1
[1.46.0/0.68.0/0.22.0/0.0.19]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.46.0
[1.45.0/0.67.0/0.21.0/0.0.18]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.45.0
[1.44.0/0.66.0/0.20.0/0.0.17]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.44.0
-3
View File
@@ -1,3 +0,0 @@
# Instructions for Claude Code
@AGENTS.md
+1 -1
View File
@@ -12,6 +12,6 @@
# https://help.github.com/en/articles/about-code-owners
#
* @MrAlias @XSAM @dashpole @pellared @dmathieu @flc1125
* @MrAlias @XSAM @dashpole @pellared @dmathieu @flc1125 @ps-mir
CODEOWNERS @MrAlias @pellared @dashpole @XSAM @dmathieu

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