Compare commits

..
50 Commits
Author SHA1 Message Date
Sebastiaan van Stijn 5457199aa5 Merge pull request #7470 from thaJeztah/29.x_backport_bump_compress
[29.x backport] vendor: github.com/klauspost/compress v1.20.2
2026-11-03 22:35:02 +01:00
Sebastiaan van Stijn cac50c5e62 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>
(cherry picked from commit b9456fd725)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 22:28:18 +01:00
Sebastiaan van Stijn 00d843b496 Merge pull request #7467 from thaJeztah/29.x_backport_bump_swarmkit
[29.x backport] vendor: github.com/moby/swarmkit/v2 v2.1.3
2026-11-03 21:22:28 +01:00
Sebastiaan van Stijn 64fe50bbea 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>
(cherry picked from commit 77ebef3df8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 21:12:39 +01:00
Paweł Gronowski 999ab16f09 Merge pull request #7464 from thaJeztah/29.x_backport_bump_jose2
[29.x backport] vendor: github.com/go-jose/go-jose/v4 v4.1.7
2026-11-03 14:41:51 +01:00
Sebastiaan van Stijn bb485bc900 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>
(cherry picked from commit 81e4a109a3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 14:25:22 +01:00
Sebastiaan van Stijn 86e51b44de Merge pull request #7461 from thaJeztah/29.x_backport_bump_yaml
[29.x backport] vendor: go.yaml.in/yaml/v3 v3.0.6 (security)
2026-11-03 14:23:29 +01:00
Paweł Gronowski d9bbcfcb4d Merge pull request #7457 from thaJeztah/29.x_backport_bump_jose
[29.x backport] vendor: github.com/go-jose/go-jose/v4 v4.1.6 (security)
2026-11-03 14:23:03 +01:00
Paweł Gronowski 2e886262b1 Merge pull request #7458 from thaJeztah/29.x_bump_version
[29.x] bump version to v29.9.3
2026-11-03 14:19:45 +01:00
Sebastiaan van Stijn a4971d1f60 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>
(cherry picked from commit 796f9633b4)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 11:57:17 +01:00
Sebastiaan van Stijn bfb5814dd5 bump version to v29.9.3
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 11:39:48 +01:00
Sebastiaan van Stijn 68e452624a 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>
(cherry picked from commit ccccec73b0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 11:31:54 +01:00
Sebastiaan van Stijn 160531c55d vendor: github.com/fvbommel/sortorder v1.2.1
full diff: https://github.com/fvbommel/sortorder/compare/v1.2.0...v1.2.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 1600418944)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-03 11:31:51 +01:00
Sebastiaan van Stijn a82e528901 Merge pull request #7418 from vvoland/7417-29.x
[29.x] Update to go1.26.10
2026-10-20 13:24:07 +02:00
Paweł Gronowski e35bc1b6ae Update to go1.26.10
These releases include 1 security fix following the security policy:

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

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

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

  We highly recommend immediately upgrading to this release.

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

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

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-20 12:42:59 +02:00
Paweł Gronowski baf6c13889 Bump version
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-20 12:40:09 +02:00
Paweł Gronowski 4051f75f69 Merge tag 'v29.9.1' into 7417-29.x
v29.9.1

# -----BEGIN PGP SIGNATURE-----
#
# iK0EABYKAFUWIQQX90wwlHYgZQhz61ZuYvmhLGnMZgUCas/KIxsUgAAAAAAEAA5t
# YW51MiwyLjUrMS4xMiwwLDMbHHBhd2VsLmdyb25vd3NraUBkb2NrZXIuY29tAAoJ
# EG5i+aEsacxmKWgBAKZGzyE7LzPW1Xy2ETngj+i8n96ZxkRPuzU7b2Rd+XLlAQCc
# YddGBSzdhrlh6EQtYdYMx7ArXfx7g8T10tGORAKqBw==
# =7Syv
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed Oct 14 20:29:55 2026 CEST
# gpg:                using EDDSA key 17F74C30947620650873EB566E62F9A12C69CC66
# gpg:                issuer "pawel.gronowski@docker.com"
# gpg: Good signature from "Paweł Gronowski <pawel.gronowski@docker.com>" [ultimate]
2026-10-20 12:39:56 +02:00
Paweł Gronowski 76321a699d Merge tag 'v29.9.0' into 7417-29.x
v29.9.0

# -----BEGIN PGP SIGNATURE-----
#
# iK0EABYKAFUWIQQX90wwlHYgZQhz61ZuYvmhLGnMZgUCasf+dhsUgAAAAAAEAA5t
# YW51MiwyLjUrMS4xMiwwLDMbHHBhd2VsLmdyb25vd3NraUBkb2NrZXIuY29tAAoJ
# EG5i+aEsacxm3EYBAKRhamCCxqMBniTJ9GtLRVn7G3gbweSztHdAzhCo70C6AP41
# K+a4eqECp+bjqTK1ldegnmdyAPZ8g8AoPMpJgSQ2CA==
# =N5Qp
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu Oct  8 22:35:02 2026 CEST
# gpg:                using EDDSA key 17F74C30947620650873EB566E62F9A12C69CC66
# gpg:                issuer "pawel.gronowski@docker.com"
# gpg: Good signature from "Paweł Gronowski <pawel.gronowski@docker.com>" [ultimate]
2026-10-20 12:39:56 +02:00
Paweł Gronowski b82456c62f Merge tag 'v29.8.2' into 7417-29.x
v29.8.2

# -----BEGIN PGP SIGNATURE-----
#
# iK0EABYKAFUWIQQX90wwlHYgZQhz61ZuYvmhLGnMZgUCar1jPxsUgAAAAAAEAA5t
# YW51MiwyLjUrMS4xMiwwLDMbHHBhd2VsLmdyb25vd3NraUBkb2NrZXIuY29tAAoJ
# EG5i+aEsacxmaQABAKG/rnQXNds4jV6qfRvaOS+tGa3Gy2hTY6o2aOgX3g3LAP4n
# OF3/gfVEcaQAK2dgxYTQnQvZi+/p69M1Bjsmy8ytBg==
# =x2Qn
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed Sep 30 21:30:07 2026 CEST
# gpg:                using EDDSA key 17F74C30947620650873EB566E62F9A12C69CC66
# gpg:                issuer "pawel.gronowski@docker.com"
# gpg: Good signature from "Paweł Gronowski <pawel.gronowski@docker.com>" [ultimate]
2026-10-20 12:39:55 +02:00
Paweł Gronowski a98becc3e3 Bump version
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-10-20 12:36:49 +02:00
Paweł Gronowski eabc65846b Merge tag 'v29.8.1' into 29.x
v29.8.1
2026-09-29 14:09:44 +02:00
Paweł Gronowski b873f57cd0 Merge tag 'v29.8.0' into 29.x
v29.8.0
2026-09-29 14:09:44 +02:00
Paweł Gronowski c8a849c2f9 Merge tag 'v29.8.0-rc.1' into 29.x
v29.8.0-rc.1
2026-09-29 14:09:44 +02:00
Paweł Gronowski f4efc1b596 Merge tag 'v29.7.2' into 29.x
v29.7.2
2026-08-11 13:21:01 +02:00
Paweł Gronowski 2747e2e3bf Merge tag 'v29.7.1' into 29.x
v29.7.1
2026-08-11 13:21:01 +02:00
Paweł Gronowski 329cdf1a9d Merge tag 'v29.7.0' into 29.x
v29.7.0
2026-08-11 13:21:01 +02:00
Paweł Gronowski 0c7e2e7203 Merge tag 'v29.7.0-rc.1' into 29.x
v29.7.0-rc.1
2026-08-11 13:21:00 +02:00
Paweł Gronowski dfc4efb1e2 Merge pull request #7109 from vvoland/update-docker
[29.x] Bump to 29.6.2
2026-07-16 18:09:24 +02:00
Paweł Gronowski dba867594c Bump to 29.6.2
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-16 12:51:30 +02:00
Paweł Gronowski d9aefe565a Merge tag 'v29.6.1' into 29.x
v29.6.1
2026-07-15 17:35:42 +02:00
Paweł Gronowski 9182b351c1 Merge tag 'v29.6.0' into 29.x
v29.6.0
2026-07-15 17:35:42 +02:00
Paweł Gronowski 0ae55a3e6c Merge tag 'v29.5.3' into 29.x
v29.5.3
2026-07-15 17:35:42 +02:00
Paweł Gronowski 029a4b21b3 Merge tag 'v29.5.2' into 29.x
v29.5.2
2026-07-15 17:35:41 +02:00
Paweł Gronowski e596fea454 Merge tag 'v29.5.1' into 29.x
v29.5.1
2026-07-15 17:35:41 +02:00
Paweł Gronowski 0c72f456aa Merge tag 'v29.5.0' into 29.x
v29.5.0
2026-07-15 17:35:41 +02:00
Paweł Gronowski 26f2736a2b Merge tag 'v29.4.1' into 29.x
v29.4.1
2026-07-15 17:35:41 +02:00
Paweł Gronowski ac4c4dfabd Merge tag 'v29.4.0' into 29.x
v29.4.0
2026-07-15 17:35:40 +02:00
Sebastiaan van Stijn 1245054535 Merge pull request #7099 from vvoland/7098-29.x
[29.x backport] scripts/sync-branch: Fix non-interactive merge
2026-07-10 08:34:26 +02:00
Paweł Gronowski f72fb0caf0 scripts/sync-branch: Fix non-interactive merge
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit f57e528457)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-09 16:52:02 +02:00
Sebastiaan van Stijn e4af2bf0d3 Merge pull request #7097 from vvoland/7091-29.x
[29.x backport] gha: Add release branch sync workflow
2026-07-09 16:35:45 +02:00
Paweł Gronowski 49a1af6aaa gha: Add release branch sync workflow
Add a manually dispatched workflow for maintainers to sync a Docker
release branch to a selected release tag.

The sync-release-branch job checks out the release branch, computes
the list of unmerged tags up to the requested tag via
scripts/unmerged-tags, merges them in order via scripts/sync-branch
using git merge --no-ff (resolving conflicts by taking the tag's
content), then pushes the result to a temporary branch.

The push-release-branch job runs after manual approval via the
docker-releases environment. It verifies that neither the release
branch nor the temporary branch moved since the sync job ran before
force-advancing the release branch and deleting the temporary branch.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 182f56fe8c)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-09 14:45:32 +02:00
Paweł Gronowski c2be9ccfc3 Merge pull request #6887 from thaJeztah/29.x_backport_pin_actions
[29.x backport] ci: pin actions to digests
2026-03-25 15:22:32 +01:00
Sebastiaan van Stijn 0da6a5121f ci: pin actions to digests
As a follow-up, we should use the full version (major.minor.patch).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 97b9e04a94)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 15:06:23 +01:00
Sebastiaan van Stijn 6b3ca8fc04 Merge pull request #6884 from thaJeztah/29.x_backport_missing_buildtags
[29.x backport] cli/command: add missing "go:build" comments
2026-03-25 15:04:52 +01:00
Paweł Gronowski f47603c290 Merge pull request #6885 from thaJeztah/29.x_backport_update_actions
[29.x backport] update actions
2026-03-25 14:23:37 +01:00
dependabot[bot] 9709c8fe08 build(deps): bump docker/metadata-action from 5 to 6
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 39d676c72d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 14:16:00 +01:00
dependabot[bot] af45a23fa9 build(deps): bump docker/bake-action from 6 to 7
Bumps [docker/bake-action](https://github.com/docker/bake-action) from 6 to 7.
- [Release notes](https://github.com/docker/bake-action/releases)
- [Commits](https://github.com/docker/bake-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: docker/bake-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 6453c4c3a7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 14:15:48 +01:00
Paweł Gronowski bc97f5ac19 Merge pull request #6883 from thaJeztah/29.x_backport_update_go1.25.8
[29.x backport] update to go1.25.8
2026-03-25 14:14:46 +01:00
Sebastiaan van Stijn 6d71967120 cli/command: add missing "go:build" comments
- commit e8dc2fce32 modernized loops to
  range over int, which requires go1.22 or later.
- commit 85ebca52fd modernized code to
  use stdlib min/max, which requires go1.21 or later.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9a471180cb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 14:11:15 +01:00
Sebastiaan van Stijn 9b51892b80 update to go1.25.8
go1.25.8 (released 2026-03-05) includes security fixes to the html/template,
net/url, and os packages, as well as bug fixes to the go command, the compiler,
and the os package. See the Go 1.25.8 milestone on our issue tracker for details.

- 1.25.8 https://github.com/golang/go/issues?q=milestone%3AGo1.25.8+label%3ACherryPickApproved
- diff: https://github.com/golang/go/compare/go1.25.7...go1.25.8
- 1.26.1 https://github.com/golang/go/issues?q=milestone%3AGo1.26.1+label%3ACherryPickApproved
- diff: https://github.com/golang/go/compare/go1.26.0...go1.26.1

---

We have just released Go versions 1.26.1 and 1.25.8, minor point releases.

These releases include 5 security fixes following the security policy:

crypto/x509: incorrect enforcement of email constraints

- When verifying a certificate chain which contains a certificate containing
  multiple email address constraints (composed of the full email address) which
  share common local portions (the portion of the address before the '@'
  character) but different domain portions (the portion of the address after the
  '@' character), these constraints will not be properly applied, and only the
  last constraint will be considered.

  This can allow certificates in the chain containing email addresses which are
  either not permitted or excluded by the relevant constraints to be returned by
  calls to Certificate.Verify. Since the name constraint checks happen after chain
  building is complete, this only applies to certificate chains which chain to
  trusted roots (root certificates either in VerifyOptions.Roots or in the system
  root certificate pool), requiring a trusted CA to issue certificates containing
  either not permitted or excluded email addresses.

  This issue only affects Go 1.26.

  Thanks to Jakub Ciolek for reporting this issue.

  This is CVE-2026-27137 and Go issue https://go.dev/issue/77952.

- crypto/x509: panic in name constraint checking for malformed certificates

  Certificate verification can panic when a certificate in the chain has an empty
  DNS name and another certificate in the chain has excluded name constraints.
  This can crash programs that are either directly verifying X.509 certificate
  chains, or those that use TLS.

  Since the name constraint checks happen after chain building is complete, this
  only applies to certificate chains which chain to trusted roots (root
  certificates either in VerifyOptions.Roots or in the system root certificate
  pool), requiring a trusted CA to issue certificates containing malformed DNS
  names.

  This issue only affects Go 1.26.

  Thanks to Jakub Ciolek for reporting this issue.

  This is CVE-2026-27138 and Go issue https://go.dev/issue/77953.

- html/template: URLs in meta content attribute actions are not escaped

  Actions which insert URLs into the content attribute of HTML meta tags are not
  escaped. This can allow XSS if the meta tag also has an http-equiv attribute
  with the value "refresh".

  A new GODEBUG setting has been added, htmlmetacontenturlescape, which can be
  used to disable escaping URLs in actions in the meta content attribute which
  follow "url=" by setting htmlmetacontenturlescape=0.

  This is CVE-2026-27142 and Go issue https://go.dev/issue/77954.

- net/url: reject IPv6 literal not at start of host

  The Go standard library function net/url.Parse insufficiently
  validated the host/authority component and accepted some invalid URLs
  by effectively treating garbage before an IP-literal as ignorable.
  The function should have rejected this as invalid.

  To prevent this behavior, net/url.Parse now rejects IPv6 literals
  that do not appear at the start of the host subcomponent of a URL.

  Thanks to Masaki Hara (https://github.com/qnighy) of Wantedly.

  This is CVE-2026-25679 and Go issue https://go.dev/issue/77578.

- os: FileInfo can escape from a Root

  On Unix platforms, when listing the contents of a directory using
  File.ReadDir or File.Readdir the returned FileInfo could reference
  a file outside of the Root in which the File was opened.

  The contents of the FileInfo were populated using the lstat system
  call, which takes the path to the file as a parameter. If a component
  of the full path of the file described by the FileInfo is replaced with
  a symbolic link, the target of the lstat can be directed to another
  location on the filesystem.

  The impact of this escape is limited to reading metadata provided by
  lstat from arbitrary locations on the filesystem. This could be used
  to probe for the presence or absence of files as well as gleaning
  metadata like file sizes, but does not permit reading or writing files
  outside the root.

  The FileInfo is now populated using fstatat.

  Thank you to Miloslav Trmač of Red Hat for reporting this issue.

  This is CVE-2026-27139 and Go issue https://go.dev/issue/77827.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f7d83cbae8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 14:08:46 +01:00
249 changed files with 2205 additions and 8714 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@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.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@cbc9d42f8c89a55623392aadd03600965b80e963 # v1.18.1
uses: docker/github-builder/.github/workflows/bake.yml@58cb9f5b71b1836d6f690c1e95effdeb9b98cb8a # v1.17.0
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@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.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.27.3"
go-version: "1.26.10"
cache: false
-
name: Initialize CodeQL
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
languages: go
-
name: Autobuild
uses: github/codeql-action/autobuild@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
-
name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
category: "/language:go"
+1 -4
View File
@@ -26,9 +26,6 @@ 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
@@ -83,4 +80,4 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
files: ./build/coverage/coverage.txt
use_oidc: true
token: ${{ secrets.CODECOV_TOKEN }}
+1 -1
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
review:
uses: docker/docker-agent-action/.github/workflows/review-pr.yml@aaa657c53cc69ed15683cd8a985d86663a0e1594 # v2.1.0
uses: docker/docker-agent-action/.github/workflows/review-pr.yml@3654ec391b070e247de2e2e3c1ff2519b6378b3a # v2.0.9
permissions:
contents: read # Read repository files and PR diffs
pull-requests: write # Post review comments
+6 -12
View File
@@ -26,9 +26,6 @@ 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:
-
@@ -36,7 +33,7 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
-
name: Test
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.0
with:
targets: test-coverage
-
@@ -44,12 +41,9 @@ jobs:
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
files: ./build/coverage/coverage.txt
use_oidc: true
token: ${{ secrets.CODECOV_TOKEN }}
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 }}
@@ -59,9 +53,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:
-
@@ -74,7 +68,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.27.3"
go-version: "1.26.10"
cache: false
-
name: Test
@@ -92,4 +86,4 @@ jobs:
with:
files: /tmp/coverage.txt
working-directory: ${{ env.GOPATH }}/src/github.com/docker/cli
use_oidc: true
token: ${{ secrets.CODECOV_TOKEN }}
+2 -2
View File
@@ -38,7 +38,7 @@ jobs:
steps:
-
name: Run
uses: docker/bake-action@59cb1203cd42bcefd40a1b6d73b589e48c86040e # v7.5.0
uses: docker/bake-action@018cb6412ab401ebaa809aa5f85966b74628600f # v7.4.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.27.3"
go-version: "1.26.10"
cache: false
-
name: Run gocompat check
+11 -1
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.27.3"
go: "1.26.10"
timeout: 5m
@@ -201,6 +201,11 @@ 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:
@@ -222,6 +227,11 @@ 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
+6 -8
View File
@@ -5,12 +5,10 @@ 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.24
ARG ALPINE_VERSION=3.23
ARG BASE_DEBIAN_DISTRO=bookworm
# BASE_DEBIAN_DISTRO sets the version of the debian base image to use,
ARG BASE_DEBIAN_DISTRO=trixie
ARG GO_VERSION=1.27.3
ARG GO_VERSION=1.26.10
# 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.
@@ -27,12 +25,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.1
ARG BUILDX_VERSION=0.38.0
# 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.7.0
ARG COMPOSE_VERSION=v5.6.0
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@@ -55,7 +53,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-14-dev pkgconf
RUN xx-apt-get install --no-install-recommends -y libc6-dev libgcc-12-dev pkgconf
FROM build-base-${BASE_VARIANT} AS goversioninfo
ARG GOVERSIONINFO_VERSION
+1 -1
View File
@@ -1 +1 @@
29.10.0
29.9.3
+2 -62
View File
@@ -10,7 +10,6 @@ import (
"fmt"
"os"
"sync"
"time"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/metadata"
@@ -33,11 +32,6 @@ 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)
@@ -75,7 +69,6 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadat
stopInstrumentation(err)
return err
}
cobra.OnFinalize(func() { finalizeHook(dockerCli) })
})
return retErr
}
@@ -90,59 +83,6 @@ 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
@@ -272,8 +212,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)
+1 -19
View File
@@ -160,25 +160,7 @@ func (tcmd *TopLevelCommand) HandleGlobalFlags() (*cobra.Command, []string, erro
return nil, nil, cmd.FlagErrorFunc()(cmd, err)
}
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
return cmd, flags.Args(), nil
}
// Initialize finalises global option parsing and initializes the docker client.
-42
View File
@@ -108,45 +108,3 @@ 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)
})
}
+13 -16
View File
@@ -146,27 +146,24 @@ 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 {
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
}
}
// 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 {
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 {
return name
}
continue
}
if i > 0 {
b.WriteByte(',')
}
b.WriteString(strings.TrimPrefix(n, "/"))
b.WriteString(name)
}
return b.String()
}
-20
View File
@@ -48,25 +48,6 @@ 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,
@@ -276,7 +257,6 @@ 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()
+2 -30
View File
@@ -10,10 +10,8 @@ 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"
@@ -22,23 +20,6 @@ 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
@@ -116,8 +97,6 @@ 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
}
@@ -160,15 +139,8 @@ func runManifestAnnotate(dockerCLI command.Cli, opts annotateOptions) error {
imageManifest.Descriptor.Platform.OSVersion = opts.osVersion
}
// 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)
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)
}
return manifestStore.Save(targetRef, imgRef, imageManifest)
}
+7 -8
View File
@@ -58,16 +58,15 @@ func TestManifestAnnotate(t *testing.T) {
assert.ErrorContains(t, cmd.Execute(), expectedError)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
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"
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.ErrorContains(t, cmd.Execute(), expectedError)
assert.NilError(t, cmd.Flags().Set("arch", "arm"))
cmd.Flags().Set("arch", "arm")
assert.NilError(t, cmd.Execute())
cmd = newInspectCommand(cli)
+47
View File
@@ -9,6 +9,53 @@ 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 {
+6 -6
View File
@@ -19,7 +19,6 @@ import (
"github.com/docker/cli/internal/tui"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@@ -227,7 +226,7 @@ func loginWithStoredCredentials(ctx context.Context, dockerCLI command.Cli, auth
return resp.Auth.Status, err
}
func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (message string, _ error) {
func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (msg string, _ error) {
// Some links documenting this:
// - https://code.google.com/archive/p/mintty/issues/56
// - https://github.com/docker/docker/issues/15272
@@ -241,12 +240,13 @@ func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, de
// If we're logging into the index server and the user didn't provide a username or password, use the device flow
if serverAddress == registry.IndexServer && opts.user == "" && opts.password == "" {
msg, err := loginWithDeviceCodeFlow(ctx, dockerCLI)
if err == nil || !errors.Is(err, manager.ErrDeviceLoginStartFail) {
var err error
msg, err = loginWithDeviceCodeFlow(ctx, dockerCLI)
// if the error represents a failure to initiate the device-code flow,
// then we fallback to regular cli credentials login
if !errors.Is(err, manager.ErrDeviceLoginStartFail) {
return msg, err
}
logrus.WithError(err).Debug("failed to start web-based login")
_, _ = fmt.Fprint(dockerCLI.Err(), "Failed to start web-based login - falling back to command line login...\n\n")
}
+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,6 +255,7 @@ 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())
@@ -262,6 +263,7 @@ 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)
@@ -269,6 +271,7 @@ 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"))
@@ -282,6 +285,7 @@ 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())
+3 -6
View File
@@ -27,13 +27,8 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
}))
cli.SetOut(outStream)
r, w, err := os.Pipe()
r, _, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r))
notifyCtx, notifyCancel := context.WithCancel(ctx)
@@ -63,6 +58,8 @@ 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)
+4 -36
View File
@@ -11,9 +11,8 @@ import (
"github.com/distribution/reference"
"github.com/docker/cli/cli/streams"
"github.com/moby/moby/api/types/jsonstream"
"github.com/docker/cli/internal/jsonstream"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client/pkg/jsonmessage"
"github.com/opencontainers/go-digest"
"github.com/theupdateframework/notary/client"
"github.com/theupdateframework/notary/tuf/data"
@@ -47,7 +46,7 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
// Count the times of calling for handleTarget,
// if it is called more that once, that should be considered an error in a trusted push.
cnt := 0
handleTarget := func(msg jsonstream.Message) {
handleTarget := func(msg jsonstream.JSONMessage) {
cnt++
if cnt > 1 {
// handleTarget should only be called once. This will be treated as an error.
@@ -79,14 +78,14 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
default:
// We want trust signatures to always take an explicit tag,
// otherwise it will act as an untrusted push.
if err := displayJSONMessages(ctx, in, ioStreams.Out(), nil); err != nil {
if err := jsonstream.Display(ctx, in, ioStreams.Out()); err != nil {
return err
}
_, _ = fmt.Fprintln(ioStreams.Err(), "No tag specified, skipping trust metadata push")
return nil
}
if err := displayJSONMessages(ctx, in, ioStreams.Out(), handleTarget); err != nil {
if err := jsonstream.Display(ctx, in, ioStreams.Out(), jsonstream.WithAuxCallback(handleTarget)); err != nil {
return err
}
@@ -148,34 +147,3 @@ func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *Repo
_, _ = fmt.Fprintf(ioStreams.Out(), "Successfully signed %s:%s\n", repoInfo.Name.Name(), tag)
return nil
}
type ctxReader struct {
err chan error
r io.Reader
}
func (r *ctxReader) Read(p []byte) (int, error) {
select {
case err := <-r.err:
return 0, err
default:
return r.r.Read(p)
}
}
// displayJSONMessages prints the JSON messages from in to out. It returns
// ctx.Err() if ctx is canceled, but not when in is closed.
func displayJSONMessages(ctx context.Context, in io.Reader, out *streams.Out, auxCallback func(jsonstream.Message)) error {
if ctx.Err() != nil {
return ctx.Err()
}
reader := &ctxReader{err: make(chan error, 1), r: in}
stop := context.AfterFunc(ctx, func() { reader.err <- ctx.Err() })
defer stop()
if err := jsonmessage.DisplayJSONMessagesStream(reader, out, out.FD(), out.IsTerminal(), auxCallback); err != nil {
return err
}
return ctx.Err()
}
+32
View File
@@ -0,0 +1,32 @@
package trust
import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/commands"
"github.com/spf13/cobra"
)
func init() {
commands.Register(newTrustCommand)
}
// newTrustCommand returns a cobra command for `trust` subcommands.
func newTrustCommand(dockerCLI command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "trust",
Short: "Manage trust on Docker images",
Args: cli.NoArgs,
RunE: command.ShowHelp(dockerCLI.Err()),
DisableFlagsInUseLine: true,
}
cmd.AddCommand(
newRevokeCommand(dockerCLI),
newSignCommand(dockerCLI),
newTrustKeyCommand(dockerCLI),
newTrustSignerCommand(dockerCLI),
newInspectCommand(dockerCLI),
)
return cmd
}
+2 -2
View File
@@ -5,12 +5,12 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cmd/docker-trust/internal/trust"
"github.com/docker/cli/internal/lazyregexp"
"github.com/spf13/cobra"
"github.com/theupdateframework/notary"
"github.com/theupdateframework/notary/trustmanager"
@@ -41,7 +41,7 @@ func newKeyGenerateCommand(dockerCLI command.Streams) *cobra.Command {
}
// key names can use lowercase alphanumeric + _ + - characters
var validKeyName = regexp.MustCompile(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
var validKeyName = lazyregexp.New(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
// validate that all of the key names are unique and are alphanumeric + _ + -
// and that we do not already have public key files in the target dir on disk
+2 -2
View File
@@ -7,12 +7,12 @@ import (
"io"
"os"
"path"
"regexp"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cmd/docker-trust/internal/trust"
"github.com/docker/cli/internal/lazyregexp"
"github.com/docker/cli/opts"
"github.com/spf13/cobra"
"github.com/theupdateframework/notary/client"
@@ -45,7 +45,7 @@ func newSignerAddCommand(dockerCLI command.Cli) *cobra.Command {
return cmd
}
var validSignerName = regexp.MustCompile(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
var validSignerName = lazyregexp.New(`^[a-z0-9][a-z0-9\_\-]*$`).MatchString
func addSigner(ctx context.Context, dockerCLI command.Cli, options signerAddOptions) error {
signerName := options.signer
-9
View File
@@ -580,15 +580,6 @@ func runDocker(ctx context.Context, dockerCli *command.DockerCli) error {
}
// Other missing or invalid plugins fall through to cmd.ExecuteContext(),
// which reports the standard unknown-command error.
//
// Cobra handles "--version" before it checks for unknown commands,
// so unset it to make "docker nonexistent --version" fail instead
// of printing the version. A global "--version" flag (as in
// "docker --version nonexistent") was already parsed, and still
// prints the version.
if !cmd.Flags().Changed("version") {
cmd.Version = ""
}
}
}
-1
View File
@@ -4156,7 +4156,6 @@ _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.24
ARG ALPINE_VERSION=3.23
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.27.3
ARG GO_VERSION=1.26.10
# 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.24
ARG ALPINE_VERSION=3.23
# 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.1
ARG BUILDX_VERSION=0.38.0
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.27.3
ARG GO_VERSION=1.26.10
# 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.24
ARG ALPINE_VERSION=3.23
# GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use.
ARG GOLANGCI_LINT_VERSION=v2.14.0
ARG GOLANGCI_LINT_VERSION=v2.10.1
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.27.3
ARG GO_VERSION=1.26.10
# 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.24
ARG MODOUTDATED_VERSION=v0.9.0
ARG ALPINE_VERSION=3.23
ARG MODOUTDATED_VERSION=v0.8.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: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
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
$ 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: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
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
$ 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: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
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
$ 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: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
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
```
+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:26.04 bash 17 seconds ago Up 16 seconds 3300-3310/tcp webapp
ca5534a51dd04bbcebe9b23ba05f389466cf0c190f1f8f182d7eea92a9671d00 ubuntu:24.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 `26.04` image:
Match containers based on the `ubuntu` version `24.04` image:
```console
$ docker ps --filter ancestor=ubuntu:26.04
$ docker ps --filter ancestor=ubuntu:24.04
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
82a598284012 ubuntu:26.04 "top" 3 minutes ago Up 3 minutes sleepy_bose
82a598284012 ubuntu:24.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:26.04 "top" 3 minutes ago Up 3 minutes sleepy_bose
82a598284012 ubuntu:24.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:trixie` image shares
its layer with the `debian:latest`. Pulling the `debian:trixie` image therefore
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
only pulls its metadata, but not its layers, because the layer is already present
locally:
```console
$ docker image pull debian:trixie
$ docker image pull debian:bookworm
trixie: Pulling from library/debian
bookworm: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:trixie
docker.io/library/debian:trixie
Status: Downloaded newer image for debian:bookworm
docker.io/library/debian:bookworm
```
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 trixie 4eacea30377a 8 days ago 124MB
debian bookworm 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:trixie` and `debian:latest` have the same image ID because they are
`debian:bookworm` 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:26.04` pulls the latest version of the Ubuntu
26.04 image.
For example, `docker pull ubuntu:24.04` pulls the latest version of the Ubuntu
24.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:26.04` image from Docker Hub:
`ubuntu:24.04` image from Docker Hub:
```console
$ docker pull ubuntu:26.04
$ docker pull ubuntu:24.04
26.04: Pulling from library/ubuntu
24.04: Pulling from library/ubuntu
125a6e411906: Pull complete
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:26.04
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.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 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 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 latest 35a88802559d 6 weeks ago 78.1MB
ubuntu resolute 35a88802559d 6 weeks ago 78.1MB
ubuntu noble 35a88802559d 6 weeks ago 78.1MB
```
### Cancel a pull
+4 -3
View File
@@ -180,12 +180,13 @@ code, and authenticate.
```console
$ docker login
Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'
USING WEB-BASED LOGIN
To sign in with credentials on the command line, use 'docker login -u <username>'
Your one-time device confirmation code is: LNFR-PGCJ
Open this URL to authenticate: https://login.docker.com/activate?user_code=LNFR-PGCJ
Press ENTER to open your browser or submit your device code here: https://login.docker.com/activate
Press ENTER to open the URL in your browser, or Ctrl+C to cancel.
Waiting for authentication in the browser…
```
After entering the code in your browser, you are authenticated to Docker Hub
+1 -1
View File
@@ -706,7 +706,7 @@ follows:
| `node.platform.os` | Node operating system | `node.platform.os==windows` |
| `node.platform.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-26.04` |
| `engine.labels` | Docker Engine's labels | `engine.labels.operatingsystem==ubuntu-24.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:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
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-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 `26.04` of the `ubuntu` image: `docker run ubuntu:26.04`.
run version `24.04` of the `ubuntu` image: `docker run ubuntu:24.04`.
#### Image digests
@@ -406,14 +406,14 @@ We have four ways to set user memory usage:
Examples:
```console
$ docker run -it ubuntu:26.04 /bin/bash
$ docker run -it ubuntu:24.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:26.04 /bin/bash
$ docker run -it -m 300M --memory-swap -1 ubuntu:24.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:26.04 /bin/bash
$ docker run -it -m 300M ubuntu:24.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:26.04 /bin/bash
$ docker run -it -m 300M --memory-swap 1G ubuntu:24.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:26.04 /bin/bash
$ docker run -it -m 500M --memory-reservation 200M ubuntu:24.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:26.04 /bin/bash
$ docker run -it --memory-reservation 1G ubuntu:24.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:26.04 /bin/bash
$ docker run -it -m 100M --oom-kill-disable ubuntu:24.04 /bin/bash
```
The following example, illustrates a dangerous way to use the flag:
```console
$ docker run -it --oom-kill-disable ubuntu:26.04 /bin/bash
$ docker run -it --oom-kill-disable ubuntu:24.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:26.04 /bin/bash
$ docker run -it --memory-swappiness=0 ubuntu:24.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:26.04 /bin/bash
$ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:24.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:26.04 /bin/bash
$ docker run -it --cpuset-cpus="1,3" ubuntu:24.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:26.04 /bin/bash
$ docker run -it --cpuset-cpus="0-2" ubuntu:24.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:26.04 /bin/bash
$ docker run -it --cpuset-mems="1,3" ubuntu:24.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:26.04 /bin/bash
$ docker run -it --cpuset-mems="0-2" ubuntu:24.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:26.04 /bin/bash
$ docker run -it --name c2 --blkio-weight 600 ubuntu:26.04 /bin/bash
$ 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
```
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:26.04 ip link add dummy0 type dummy
$ docker run -it --rm ubuntu:24.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:26.04 ip link add dummy0 type dummy
$ docker run -it --rm --cap-add=NET_ADMIN ubuntu:24.04 ip link add dummy0 type dummy
```
To mount a FUSE based filesystem, you need to combine both `--cap-add` and
-16
View File
@@ -62,22 +62,6 @@ func TestNonexistingHelp(t *testing.T) {
})
}
// TestNonexistingVersion ensures correct behaviour when invoking a
// nonexistent plugin with `--version`.
func TestNonexistingVersion(t *testing.T) {
run, _, cleanup := prepare(t)
defer cleanup()
for _, flag := range []string{"--version", "-v"} {
res := icmd.RunCmd(run("nonexistent", flag))
res.Assert(t, icmd.Expected{
ExitCode: 1,
Out: icmd.None,
})
golden.Assert(t, res.Stderr(), "docker-nonexistent-err.golden")
}
}
// TestRunBad ensures correct behaviour when running an existent but invalid plugin
func TestRunBad(t *testing.T) {
run, _, cleanup := prepare(t)
+1 -1
View File
@@ -30,5 +30,5 @@ func TestOauthLogin(t *testing.T) {
assert.NilError(t, err)
output, _ := io.ReadAll(p)
assert.Check(t, strings.Contains(string(output), "Using web-based login"), string(output))
assert.Check(t, strings.Contains(string(output), "USING WEB-BASED LOGIN"), string(output))
}
+14 -27
View File
@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/docker/cli/cli/config/credentials"
@@ -18,6 +17,8 @@ import (
"github.com/docker/cli/internal/registry"
"github.com/docker/cli/internal/tui"
"github.com/morikuni/aec"
"github.com/sirupsen/logrus"
"github.com/pkg/browser"
)
@@ -82,18 +83,19 @@ var ErrDeviceLoginStartFail = errors.New("failed to start device code flow login
// The retrieved tokens are stored in the credentials store (under a separate
// key), and the refresh token is concatenated with the client ID.
func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.AuthConfig, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
state, err := m.api.GetDeviceCode(ctx, m.audience)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrDeviceLoginStartFail, err)
logrus.Debugf("failed to start device code login: %v", err)
return nil, ErrDeviceLoginStartFail
}
if state.UserCode == "" {
return nil, fmt.Errorf("%w: missing user code", ErrDeviceLoginStartFail)
logrus.Debugf("failed to start device code login: missing user code")
return nil, ErrDeviceLoginStartFail
}
_, _ = fmt.Fprintln(w, aec.Bold.Apply("\nUSING WEB-BASED LOGIN"))
var out tui.Output
switch stream := w.(type) {
case *streams.Out:
@@ -101,10 +103,9 @@ func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.Aut
default:
out = tui.NewOutput(streams.NewOut(w))
}
out.PrintNote("Using web-based login. To sign in with credentials on the command line, use 'docker login -u <username>'\n")
_, _ = fmt.Fprintln(w, "Your one-time device confirmation code is:", aec.Bold.Apply(state.UserCode))
_, _ = fmt.Fprintln(w, "Open this URL to authenticate:", aec.Underline.Apply(state.VerificationURI))
_, _ = fmt.Fprintln(w, "\n"+aec.Bold.Apply("Press ENTER")+" to open the URL in your browser, or "+aec.Bold.Apply("Ctrl+C")+" to cancel.")
out.PrintNote("To sign in with credentials on the command line, use 'docker login -u <username>'\n")
_, _ = fmt.Fprintf(w, "\nYour one-time device confirmation code is: "+aec.Bold.Apply("%s\n"), state.UserCode)
_, _ = fmt.Fprintf(w, aec.Bold.Apply("Press ENTER")+" to open your browser or submit your device code here: "+aec.Underline.Apply("%s\n"), strings.Split(state.VerificationURI, "?")[0])
tokenResChan := make(chan api.TokenResponse)
waitForTokenErrChan := make(chan error)
@@ -119,25 +120,11 @@ func (m *OAuthManager) LoginDevice(ctx context.Context, w io.Writer) (*types.Aut
go func() {
reader := bufio.NewReader(os.Stdin)
if _, err := reader.ReadString('\n'); err != nil || ctx.Err() != nil {
return
}
err := m.openBrowser(state.VerificationURI)
if ctx.Err() != nil {
return
}
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
_, _ = fmt.Fprintln(w, "No browser found. Open the URL above manually to continue.")
} else {
_, _ = fmt.Fprintln(w, "Failed to open browser:", err)
_, _ = fmt.Fprintln(w, "Open the URL above manually to continue.")
}
return
}
_, _ = fmt.Fprintln(w, "\nOpening browser…")
_, _ = reader.ReadString('\n')
_ = m.openBrowser(state.VerificationURI)
}()
_, _ = fmt.Fprint(w, "\nWaiting for authentication in the browser…\n")
var tokenRes api.TokenResponse
select {
case <-ctx.Done():
+2 -2
View File
@@ -69,10 +69,10 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
// get the http transport, this will be used in a client to upload manifest
base := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: endpoint.TLSConfig,
DisableKeepAlives: true,
+3 -6
View File
@@ -27,13 +27,8 @@ func TerminatePrompt(ctx context.Context, t *testing.T, cmd *cobra.Command, cli
}))
cli.SetOut(outStream)
r, w, err := os.Pipe()
r, _, err := os.Pipe()
assert.NilError(t, err)
t.Cleanup(func() {
_ = w.Close()
_ = r.Close()
})
cli.SetIn(streams.NewIn(r))
notifyCtx, notifyCancel := context.WithCancel(ctx)
@@ -63,6 +58,8 @@ 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)
+6 -14
View File
@@ -83,24 +83,16 @@ set as the **URL**, the repository is cloned locally and then sent as the contex
Add a line to /etc/hosts. The format is hostname=ip, or hostname:ip.
The **--add-host** option can be set multiple times.
**--build-arg** *name*[=*value*]
Set a build-time variable. The *name* is the variable name, as declared
by an `ARG` instruction in the Dockerfile. If *value* is omitted, the
value of the variable *name* from the local environment is used; if it is
not set there either, the default from the `ARG` instruction (if any) is
used.
Build-time variables are available as environment variables to commands
run by the Dockerfile's `RUN` instructions, and can be used for variable
expansion in other Dockerfile instructions. An environment variable defined
by an `ENV` instruction always overrides an `ARG` of the same name. This
mechanism is not meant for passing secret values.
**--build-arg** *variable*
name and value of a **buildarg**.
For example, if you want to pass a value for `http_proxy`, use
`--build-arg=http_proxy="http://some.proxy.url"`
See also https://docs.docker.com/reference/dockerfile/#arg and
https://docs.docker.com/reference/cli/docker/buildx/build/#build-arg.
Users pass these values at build-time. Docker uses the `buildargs` as the
environment context for command(s) run via the Dockerfile's `RUN` instruction
or for variable expansion in other Dockerfile instructions. This is not meant
for passing secret values. [Read more about the buildargs instruction](https://docs.docker.com/engine/reference/builder/#arg)
**--cache-from** ""
Set image that will be used as a build cache source.
+2 -2
View File
@@ -48,10 +48,10 @@ Valid placeholders for the Go template are listed below:
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a87ecb4f327c ubuntu:26.04 /bin/sh -c #(nop) MA 20 minutes ago Exit 0 desperate_brattain
a87ecb4f327c ubuntu:24.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:26.04 /bin/sh -c #(nop) MA 2 weeks ago Exit 0 drunk_pike
41d50ecd2f57 ubuntu:24.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 26.04 or 24.04, etc. to manage different
called ubuntu. It may be tagged with 24.04 or 22.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:trixie` image shares
its layer with the `debian:latest`. Pulling the `debian:trixie` image therefore
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
only pulls its metadata, but not its layers, because the layer is already present
locally:
$ docker image pull debian:trixie
$ docker image pull debian:bookworm
trixie: Pulling from library/debian
bookworm: Pulling from library/debian
Digest: sha256:3f1d6c17773a45c97bd8f158d665c9709d7b29ed7917ac934086ad96f92e4510
Status: Downloaded newer image for debian:trixie
docker.io/library/debian:trixie
Status: Downloaded newer image for debian:bookworm
docker.io/library/debian:bookworm
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 trixie 4eacea30377a 8 days ago 124MB
debian bookworm 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:trixie` and `debian:latest` have the same image ID because they are
`debian:bookworm` 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:26.04` pulls the latest version of the Ubuntu
26.04 image.
For example, `docker image pull ubuntu:24.04` pulls the latest version of the Ubuntu
24.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:26.04` image from Docker Hub:
`ubuntu:24.04` image from Docker Hub:
$ docker image pull ubuntu:26.04
$ docker image pull ubuntu:24.04
26.04: Pulling from library/ubuntu
24.04: Pulling from library/ubuntu
125a6e411906: Pull complete
Digest: sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
Status: Downloaded newer image for ubuntu:26.04
docker.io/library/ubuntu:26.04
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.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 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 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 latest 35a88802559d 6 weeks ago 78.1MB
ubuntu resolute 35a88802559d 6 weeks ago 78.1MB
ubuntu noble 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:26.04) die
2015-05-12T15:52:12.999999999Z07:00 4386fb97867d: (from ubuntu:26.04) stop
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-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:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:24.04)
2014-09-03T17:42:14.999999999Z07:00 container stop 7805c1d35632 (image=redis:7.2)
$ 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 '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 '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:26.04)
2014-05-10T17:42:14.999999999Z07:00 container stop 4386fb97867d (image=ubuntu:26.04)
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-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: 6.8.0-31-generic
Operating System: Ubuntu 24.04 LTS
Kernel Version: 5.15.0-25-generic
Operating System: Ubuntu 22.04 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
+8 -15
View File
@@ -88,20 +88,13 @@ if [ "$CGO_ENABLED" = "1" ] && [ "$(go env GOOS)" != "windows" ]; then
fi
export GO_BUILDMODE
# 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
}
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
if [ "$CGO_ENABLED" = "1" ] && [ "$GO_LINKMODE" = "static" ] && [ "$(go env GOOS)" = "linux" ]; then
GO_LDFLAGS="$GO_LDFLAGS -linkmode external -extldflags -static"
fi
@@ -135,7 +128,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"
GO_LDFLAGS="$GO_LDFLAGS -s -w"
fi
export GO_LDFLAGS="$GO_LDFLAGS" # https://github.com/koalaman/shellcheck/issues/2064
+22 -23
View File
@@ -21,7 +21,7 @@ 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.12
github.com/docker/docker-credential-helpers v0.9.9
github.com/docker/go-connections v0.8.2
github.com/docker/go-units v0.5.0
github.com/fvbommel/sortorder v1.2.1
@@ -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.2-0.20261106011722-402d0a16f131
github.com/moby/moby/client v0.6.3-0.20261106011722-402d0a16f131
github.com/moby/moby/api v1.56.1
github.com/moby/moby/client v0.6.2
github.com/moby/patternmatcher v0.6.1
github.com/moby/swarmkit/v2 v2.1.3
github.com/moby/sys/atomicwriter v0.1.0
github.com/moby/sys/capability v0.5.0
github.com/moby/sys/capability v0.4.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.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.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.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
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
gotest.tools/v3 v3.5.2
tags.cncf.io/container-device-interface v1.1.1
)
require (
github.com/Azure/go-ansiterm v0.0.0-20261013165250-51075c6ea6bc // indirect
github.com/Azure/go-ansiterm v0.0.0-20261006220739-8c912ac31dd4 // 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
@@ -99,14 +99,13 @@ 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.47.0 // indirect
go.opentelemetry.io/otel/log v1.47.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.46.0 // indirect
go.opentelemetry.io/proto/otlp v1.11.0 // indirect
golang.org/x/mod v0.42.0 // indirect
golang.org/x/net v0.62.0 // indirect
golang.org/x/mod v0.41.0 // indirect
golang.org/x/net v0.60.0 // indirect
golang.org/x/time v0.16.0 // 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/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
google.golang.org/grpc v1.83.2 // indirect
google.golang.org/protobuf v1.36.12 // indirect
)
+48 -48
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-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/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/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.12 h1:hAgjJcMuC17DPf0Kl/HQSZQ7cxVo+wEA8Oo1SzkmqFg=
github.com/docker/docker-credential-helpers v0.9.12/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
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/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=
@@ -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.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/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/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.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.5.0 h1:Bm4oD9xGCtZguPnaoQy1/jvKTSwZHMvM0FrnxNYtGYU=
github.com/moby/sys/capability v0.5.0/go.mod h1:i+0cXvNSriGrL3C6sxnmlmGL5HVU0OdxocizXdC8A+g=
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/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,28 +155,26 @@ 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.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/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/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=
@@ -189,31 +187,31 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
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.42.0 h1:ICeL3t2L30ljSPHHxDnR4fqVcBt/zR2zJAb9juavmQg=
golang.org/x/mod v0.42.0/go.mod h1:u5fzIrRInkL8MaO1cbRkUHT64v303YIT5KEqpNr7jRs=
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/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.62.0 h1:18ELalfM5+XNRwzM2nYqXsZQ9ByS1uhj2O/U7+5jqRY=
golang.org/x/net v0.62.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI=
golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU=
golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
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.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
golang.org/x/sync v0.23.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.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/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/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.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
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/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=
@@ -226,10 +224,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-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/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/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=
@@ -237,5 +235,7 @@ 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=
+5 -7
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type csiEntryState struct {
baseState
}
@@ -15,11 +13,11 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
}
switch {
case slices.Contains(alphabetics, b):
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case slices.Contains(csiCollectables, b):
case sliceContains(csiCollectables, b):
return csiState.parser.csiParam, nil
case slices.Contains(executors, b):
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
@@ -35,9 +33,9 @@ func (csiState csiEntryState) Transition(s state) error {
return csiState.parser.csiDispatch()
case csiState.parser.csiParam:
switch {
case slices.Contains(csiParams, csiState.parser.context.currentChar):
case sliceContains(csiParams, csiState.parser.context.currentChar):
_ = csiState.parser.collectParam()
case slices.Contains(intermeds, csiState.parser.context.currentChar):
case sliceContains(intermeds, csiState.parser.context.currentChar):
_ = csiState.parser.collectInter()
}
}
+3 -5
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type csiParamState struct {
baseState
}
@@ -15,11 +13,11 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
}
switch {
case slices.Contains(alphabetics, b):
case sliceContains(alphabetics, b):
return csiState.parser.ground, nil
case slices.Contains(csiCollectables, b):
case sliceContains(csiCollectables, b):
return csiState, csiState.parser.collectParam()
case slices.Contains(executors, b):
case sliceContains(executors, b):
return csiState, csiState.parser.execute()
}
+3 -5
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type escapeIntermediateState struct {
baseState
}
@@ -14,11 +12,11 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
}
switch {
case slices.Contains(intermeds, b):
case sliceContains(intermeds, b):
return escState, escState.parser.collectInter()
case slices.Contains(executors, b):
case sliceContains(executors, b):
return escState, escState.parser.execute()
case slices.Contains(escapeIntermediateToGroundBytes, b):
case sliceContains(escapeIntermediateToGroundBytes, b):
return escState.parser.ground, nil
}
+3 -5
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type escapeState struct {
baseState
}
@@ -18,11 +16,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 slices.Contains(executors, b):
case sliceContains(executors, b):
return escState, escState.parser.execute()
case slices.Contains(escapeToGroundBytes, b):
case sliceContains(escapeToGroundBytes, b):
return escState.parser.ground, nil
case slices.Contains(intermeds, b):
case sliceContains(intermeds, b):
return escState.parser.escapeIntermediate, nil
}
+2 -4
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type groundState struct {
baseState
}
@@ -15,10 +13,10 @@ func (gs groundState) Handle(b byte) (s state, e error) {
}
switch {
case slices.Contains(printables, b):
case sliceContains(printables, b):
return gs, gs.parser.print()
case slices.Contains(executors, b):
case sliceContains(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, ...any)
logf func(string, ...interface{})
}
type Option func(*AnsiParser)
func WithLogf(f func(string, ...any)) Option {
func WithLogf(f func(string, ...interface{})) 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 ...any) {
ap.logf = func(s string, v ...interface{}) {
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, ...any) {}
ap.logf = func(string, ...interface{}) {}
}
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 range remaining {
for i := 0; i < remaining; i++ {
ints = append(ints, dflt)
}
}
+2 -4
View File
@@ -1,7 +1,5 @@
package ansiterm
import "slices"
type state interface {
Enter() error
Exit() error
@@ -34,7 +32,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 slices.Contains(toGroundBytes, b):
case sliceContains(toGroundBytes, b):
return base.parser.ground, nil
}
@@ -54,7 +52,7 @@ func (base baseState) Transition(s state) error {
execBytes = append(execBytes, 0x99)
execBytes = append(execBytes, 0x9A)
if slices.Contains(execBytes, base.parser.context.currentChar) {
if sliceContains(execBytes, base.parser.context.currentChar) {
return base.parser.execute()
}
}
+11
View File
@@ -0,0 +1,11 @@
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 @@
//go:build windows
// +build windows
package winterm
+90 -96
View File
@@ -1,17 +1,14 @@
//go:build windows
// +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.
@@ -29,50 +26,51 @@ import (
// -- The value is not referenced by the method after passing the pointer to Windows
//
// See http://golang.org/doc/go1.3.
// ===========================================================================================================
//===========================================================================================================
var (
kernel32DLL = windows.NewLazyDLL("kernel32.dll")
kernel32DLL = syscall.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")
)
// Console modes
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
// Windows Console constants
const (
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
// 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_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
)
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
// 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 (
// 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.
FOREGROUND_BLUE uint16 = 0x0001
FOREGROUND_GREEN uint16 = 0x0002
FOREGROUND_RED uint16 = 0x0004
@@ -88,29 +86,23 @@ 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.
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
)
// 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
// 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 return codes
WAIT_ABANDONED = 0x00000080
WAIT_FAILED = 0xFFFFFFFF
WAIT_SIGNALED = 0x0000000
WAIT_TIMEOUT = 0x00000102
// WaitForSingleObject wait durations.
const (
WAIT_INFINITE = windows.INFINITE
// WaitForSingleObject wait duration
WAIT_INFINITE = 0xFFFFFFFF
WAIT_ONE_SECOND = 1000
WAIT_HALF_SECOND = 500
WAIT_QUARTER_SECOND = 250
@@ -130,8 +122,6 @@ 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
@@ -140,11 +130,17 @@ type (
MaximumWindowSize COORD
}
// COORD is identical to [windows.Coord] but implements [fmt.Stringer].
COORD windows.Coord
COORD struct {
X int16
Y int16
}
// SMALL_RECT is identical to [windows.SmallRect] but implements [fmt.Stringer].
SMALL_RECT windows.SmallRect
SMALL_RECT struct {
Left int16
Top int16
Right int16
Bottom int16
}
// INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx.
@@ -193,45 +189,43 @@ 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 {
return windows.SetConsoleCursorPosition(windows.Handle(handle), windows.Coord(coord))
r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord))
use(coord)
return checkError(r1, r2, err)
}
// GetConsoleMode gets the console mode for the given handle.
// GetConsoleMode gets the console mode for given file descriptor
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx.
func GetConsoleMode(handle uintptr) (mode uint32, err error) {
err = windows.GetConsoleMode(windows.Handle(handle), &mode)
err = syscall.GetConsoleMode(syscall.Handle(handle), &mode)
return mode, err
}
// SetConsoleMode sets the console mode for the given handle.
// SetConsoleMode sets the console mode for given file descriptor
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
func SetConsoleMode(handle uintptr, mode uint32) error {
return windows.SetConsoleMode(windows.Handle(handle), mode)
r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0)
use(mode)
return checkError(r1, r2, err)
}
// 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) {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(handle), &info); err != nil {
info := CONSOLE_SCREEN_BUFFER_INFO{}
err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0))
if err != nil {
return nil, err
}
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
return &info, 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)))
runtime.KeepAlive(scrollRect)
runtime.KeepAlive(clipRect)
runtime.KeepAlive(destOrigin)
runtime.KeepAlive(char)
use(scrollRect)
use(clipRect)
use(destOrigin)
use(char)
return checkError(r1, r2, err)
}
@@ -239,7 +233,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))
runtime.KeepAlive(coord)
use(coord)
return checkError(r1, r2, err)
}
@@ -248,7 +242,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)
runtime.KeepAlive(attribute)
use(attribute)
return checkError(r1, r2, err)
}
@@ -257,8 +251,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)))
runtime.KeepAlive(isAbsolute)
runtime.KeepAlive(rect)
use(isAbsolute)
use(rect)
return checkError(r1, r2, err)
}
@@ -266,9 +260,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)))
runtime.KeepAlive(buffer)
runtime.KeepAlive(bufferSize)
runtime.KeepAlive(bufferCoord)
use(buffer)
use(bufferSize)
use(bufferCoord)
return checkError(r1, r2, err)
}
@@ -276,7 +270,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)))
runtime.KeepAlive(buffer)
use(buffer)
return checkError(r1, r2, err)
}
@@ -284,19 +278,15 @@ 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) {
event, err := windows.WaitForSingleObject(windows.Handle(handle), msWait)
if err != nil {
return false, err
}
switch event {
case windows.WAIT_ABANDONED, uint32(windows.WAIT_TIMEOUT):
r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait)))
switch r1 {
case WAIT_ABANDONED, WAIT_TIMEOUT:
return false, nil
case windows.WAIT_OBJECT_0:
case WAIT_SIGNALED:
return true, nil
default:
return false, nil
}
use(msWait)
return false, err
}
// String helpers
@@ -331,3 +321,7 @@ 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 @@
//go:build windows
// +build windows
package winterm
+33 -11
View File
@@ -1,12 +1,10 @@
//go:build windows
// +build windows
package winterm
const (
horizontal = iota
vertical
line
column
)
func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT {
@@ -60,20 +58,44 @@ 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
}
return h.setCursorPosition(position, h.getCursorWindow(info))
if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) moveCursorLine(param int) error {
return h.moveCursor(line, param)
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
}
func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error {
return h.moveCursor(column, param)
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
}
+13 -3
View File
@@ -1,4 +1,4 @@
//go:build windows
// +build windows
package winterm
@@ -50,7 +50,12 @@ func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD,
coordStart.X, coordStart.Y = xCurrent, yCurrent
coordEnd.X, coordEnd.Y = xEnd, yEnd
return h.clearRect(attributes, coordStart, coordEnd)
err = h.clearRect(attributes, coordStart, coordEnd)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error {
@@ -70,5 +75,10 @@ func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD,
buffer[i] = char
}
return WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, &region)
if err != nil {
return err
}
return nil
}
+11 -4
View File
@@ -1,4 +1,4 @@
//go:build windows
// +build windows
package winterm
@@ -39,8 +39,9 @@ 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 {
@@ -71,7 +72,10 @@ func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSO
Attributes: h.attributes,
}
return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) deleteCharacters(param int) error {
@@ -107,5 +111,8 @@ func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *
Attributes: h.attributes,
}
return ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char)
if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil {
return err
}
return nil
}
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build windows
// +build windows
package winterm
+33 -19
View File
@@ -1,4 +1,4 @@
//go:build windows
// +build windows
package winterm
@@ -169,7 +169,9 @@ func (h *windowsAnsiEventHandler) executeLF() error {
return err
}
h.logf("Resetting cursor position for LF without CR")
return SetConsoleCursorPosition(h.fd, pos)
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
}
}
return nil
@@ -371,7 +373,7 @@ func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
}
window := h.getCursorWindow(info)
position := COORD{X: window.Left + int16(col) - 1, Y: window.Top + int16(row) - 1}
position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1}
return h.setCursorPosition(position, window)
}
@@ -421,7 +423,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
targetWidth = 132
}
if info.Size.X < targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{X: targetWidth, Y: info.Size.Y}); err != nil {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err)
return err
}
@@ -434,12 +436,12 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
return err
}
if info.Size.X > targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{X: targetWidth, Y: info.Size.Y}); err != nil {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
h.logf("set buffer failed: %v", err)
return err
}
}
return SetConsoleCursorPosition(h.fd, COORD{X: 0, Y: 0})
return SetConsoleCursorPosition(h.fd, COORD{0, 0})
}
func (h *windowsAnsiEventHandler) ED(param int) error {
@@ -466,15 +468,15 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
switch param {
case 0:
start = info.CursorPosition
end = COORD{X: info.Size.X - 1, Y: info.Size.Y - 1}
end = COORD{info.Size.X - 1, info.Size.Y - 1}
case 1:
start = COORD{X: 0, Y: 0}
start = COORD{0, 0}
end = info.CursorPosition
case 2:
start = COORD{X: 0, Y: 0}
end = COORD{X: info.Size.X - 1, Y: info.Size.Y - 1}
start = COORD{0, 0}
end = COORD{info.Size.X - 1, info.Size.Y - 1}
}
err = h.clearRange(h.attributes, start, end)
@@ -493,7 +495,9 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err
}
return SetConsoleWindowInfo(h.fd, true, window)
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
return err
}
}
return nil
@@ -521,18 +525,23 @@ func (h *windowsAnsiEventHandler) EL(param int) error {
switch param {
case 0:
start = info.CursorPosition
end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
end = COORD{info.Size.X, info.CursorPosition.Y}
case 1:
start = COORD{X: 0, Y: info.CursorPosition.Y}
start = COORD{0, info.CursorPosition.Y}
end = info.CursorPosition
case 2:
start = COORD{X: 0, Y: info.CursorPosition.Y}
end = COORD{X: info.Size.X, Y: info.CursorPosition.Y}
start = COORD{0, info.CursorPosition.Y}
end = COORD{info.Size.X, info.CursorPosition.Y}
}
return h.clearRange(h.attributes, start, end)
err = h.clearRange(h.attributes, start, end)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) IL(param int) error {
@@ -602,7 +611,12 @@ func (h *windowsAnsiEventHandler) SGR(params []int) error {
if h.inverted {
attributes = invertAttributes(attributes)
}
return SetConsoleTextAttribute(h.fd, attributes)
err := SetConsoleTextAttribute(h.fd, attributes)
if err != nil {
return err
}
return nil
}
func (h *windowsAnsiEventHandler) SU(param int) error {
@@ -688,8 +702,8 @@ func (h *windowsAnsiEventHandler) Flush() error {
}
charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}}
size := COORD{X: 1, Y: 1}
position := COORD{X: 0, Y: 0}
size := COORD{1, 1}
position := COORD{0, 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
-1
View File
@@ -52,7 +52,6 @@ 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
@@ -0,0 +1 @@
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.57"
const MaxAPIVersion = "1.56"
// 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.Dialer{Config: tlsConfig}).DialContext(ctx, cli.proto, cli.addr)
return tls.Dial(cli.proto, cli.addr, tlsConfig)
}
return net.Dial(cli.proto, cli.addr)
}
+1 -3
View File
@@ -100,10 +100,8 @@ 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)
}
-16
View File
@@ -5,21 +5,6 @@ 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
@@ -119,7 +104,6 @@ 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
+15 -63
View File
@@ -13,6 +13,7 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"syscall"
@@ -24,75 +25,26 @@ 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) {
last, err := findLastCap()
if err != nil {
return 0, fmt.Errorf("unable to get last capability: %w", err)
}
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)
f, err := os.Open("/proc/sys/kernel/cap_last_cap")
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
buf := make([]byte, 11)
l, err := f.Read(buf)
f.Close()
if err != nil {
return 0, err
}
// 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
}
buf = buf[:l]
last, err := strconv.Atoi(strings.TrimSpace(string(buf)))
if err != nil {
return 0, err
}
return 0, fmt.Errorf("PR_CAPBSET_READ returned EINVAL for %s", minLastCap)
}
return Cap(last), nil
})
func capUpperMask() uint32 {
last, err := lastCap()
+3 -4
View File
@@ -141,17 +141,16 @@ func setVfsCap(path string, data *vfscapData) (err error) {
return
}
var size uintptr
switch data.version {
case 1:
if data.version == 1 {
data.magic = vfsCapVer1
size = vfscapDataSizeV1
case 2:
} else if data.version == 2 {
data.magic = vfsCapVer2
if data.effective[0] != 0 || data.effective[1] != 0 {
data.magic |= vfsCapFlageffective
}
size = vfscapDataSizeV2
default:
} else {
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,31 +10,12 @@ import (
"go.opentelemetry.io/otel/trace"
)
// Legacy HTTP attribute keys retained for compatibility.
// Attribute keys that can be added to a span.
const (
// 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")
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)
)
// Filter is a predicate used to determine whether a given http.request should
@@ -143,15 +143,14 @@ const (
)
// WithMessageEvents configures the Handler to record the specified events
// (span.AddEvent) on spans. By default, no read or write events are recorded.
// (span.AddEvent) on spans. By default only summary attributes are added at the
// end of the request.
//
// Valid events are:
// - 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.
// - 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
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(int64) {
span.AddEvent("read")
readRecordFunc = func(n int64) {
span.AddEvent("read", trace.WithAttributes(ReadBytesKey.Int64(n)))
}
}
@@ -150,8 +150,8 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
writeRecordFunc := func(int64) {}
if h.writeEvent {
writeRecordFunc = func(int64) {
span.AddEvent("write")
writeRecordFunc = func(n int64) {
span.AddEvent("write", trace.WithAttributes(WroteBytesKey.Int64(n)))
}
}
@@ -180,21 +180,12 @@ 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)
if rCtx.Pattern != "" {
span.SetName(h.spanNameFormatter(h.operation, rCtx))
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
if r.Pattern != "" {
span.SetName(h.spanNameFormatter(h.operation, r))
}
statusCode := rww.StatusCode()
@@ -213,9 +204,9 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http
ServerName: h.server,
ResponseSize: bytesWritten,
MetricAttributes: semconv.MetricAttributes{
Req: rCtx,
Req: r,
StatusCode: statusCode,
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(rCtx)...),
AdditionalAttributes: append(labeler.Get(), h.metricAttributesFromRequest(r)...),
},
MetricData: semconv.MetricData{
RequestSize: bytesRead,
@@ -38,9 +38,11 @@ func SplitHostPort(hostport string) (host string, port int) {
host = hostport[1:addrEnd]
return host, port
}
} else if !strings.Contains(hostport, ":") {
host = hostport
return host, port
} else {
if i := strings.LastIndexByte(hostport, ':'); i < 0 {
host = hostport
return host, port
}
}
host, pStr, err := net.SplitHostPort(hostport)
@@ -56,27 +56,3 @@ 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,7 +9,6 @@ import (
"io"
"net/http"
"net/http/httptrace"
"sync"
"sync/atomic"
"time"
@@ -20,6 +19,7 @@ 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,142 +82,6 @@ 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.
@@ -246,20 +110,33 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx))
}
labeler, found := ClientLabelerFromContext(ctx)
labeler, found := LabelerFromContext(ctx)
if !found {
ctx = ContextWithClientLabeler(ctx, labeler)
ctx = ContextWithLabeler(ctx, labeler)
}
r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request.
// 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)
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
}
}
span.SetAttributes(t.semconv.RequestTraceAttrs(r)...)
@@ -270,32 +147,29 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) {
res, err = ensureResponseBody(t.rt, r, res)
}
requestDuration := time.Since(requestStartTime)
// Record the metrics on error or no error.
statusCode := 0
if err == nil {
statusCode = res.StatusCode
}
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,
)
var requestSize int64
if lastBW != nil {
requestSize = lastBW.BytesRead()
}
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))
@@ -389,7 +263,8 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
case nil:
// nothing to do here but fall through to the return
case io.EOF:
wb.recordMetricsOnce()
wb.recordBytesRead()
wb.span.End()
default:
wb.span.SetAttributes(otelsemconv.ErrorType(err))
wb.span.SetStatus(codes.Error, err.Error())
@@ -397,24 +272,21 @@ func (wb *wrappedBody) Read(b []byte) (int, error) {
return n, err
}
// 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()).
// 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()).
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 {
// Finalize telemetry before delegating to the underlying Close, which
// may block (e.g. upgraded streams or custom RoundTripper bodies).
wb.recordMetricsOnce()
wb.recordBytesRead()
wb.span.End()
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.72.0"
const Version = "0.71.0"
+8 -4
View File
@@ -230,6 +230,13 @@ 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
@@ -265,10 +272,7 @@ formatters:
- golines
settings:
gofumpt:
extra:
group-params: true
clothe-returns: true
balance-calls: true
extra-rules: true
goimports:
local-prefixes:
- go.opentelemetry.io/otel
+1 -90
View File
@@ -11,93 +11,6 @@ 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].
@@ -3897,9 +3810,7 @@ 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.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
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.46.0...HEAD
[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
@@ -0,0 +1,3 @@
# 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 @ps-mir
* @MrAlias @XSAM @dashpole @pellared @dmathieu @flc1125
CODEOWNERS @MrAlias @pellared @dashpole @XSAM @dmathieu
+9 -11
View File
@@ -779,7 +779,7 @@ func newInstrumentation() (*instrumentation, error) {
if !x.Observability.Enabled() {
return nil, nil
}
meter := otel.GetMeterProvider().Meter(
"<component-package-name>",
metric.WithInstrumentationVersion(sdk.Version()),
@@ -949,7 +949,7 @@ func BenchmarkExportSpans(b *testing.B) {
{"ObsDisabled", false},
{"ObsEnabled", true},
}
for _, scenario := range scenarios {
b.Run(scenario.name, func(b *testing.B) {
b.Setenv(
@@ -980,7 +980,7 @@ func newInstrumentation() (*instrumentation, error) {
if !x.Observability.Enabled() {
return nil, nil
}
m := otel.GetMeterProvider().Meter(/* initialize meter */)
counter, err := otelconv.NewSDKComponentCounter(m)
// Use the partially initialized counter if available.
@@ -996,7 +996,7 @@ func newInstrumentation() *instrumentation {
if !x.Observability.Enabled() {
return nil, nil
}
m := otel.GetMeterProvider().Meter(/* initialize meter */)
counter, err := otelconv.NewSDKComponentCounter(m)
if err != nil {
@@ -1023,7 +1023,7 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
if e.inst.Enabled(ctx) {
e.inst.recordSpanExportStarted(ctx, len(spans))
}
err := e.doExport(ctx, spans)
if e.inst.Enabled(ctx) {
@@ -1043,11 +1043,11 @@ func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan)
func (e *Exporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error {
// ❌ Do not break the context propagation.
e.inst.recordSpanExportStarted(context.Background(), len(spans))
err := e.doExport(ctx, spans)
/* ... */
return err
}
```
@@ -1118,7 +1118,7 @@ func TestObservability(t *testing.T) {
// Reset component ID counter to ensure deterministic component names.
componentIDCounter.Store(0)
/* ... test code ... */
}
```
@@ -1203,20 +1203,18 @@ For more information about the maintainer role, see the [community repository](h
### Approvers
- [Flc](https://github.com/flc1125), Independent
- [Puneet Singh](https://github.com/ps-mir), Independent
For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver).
### Triagers
- [Marc Schäfer](https://github.com/marcschaeferger), T&A SYSTEME GmbH
- [Alex Kats](https://github.com/akats7), Capital One
For more information about the triager role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#triager).
### Emeritus
- [Aaron Clawson](https://github.com/MadVikingGod)
- [Alex Kats](https://github.com/akats7)
- [Anthony Mirabella](https://github.com/Aneurysm9)
- [Cheng-Zhen Yang](https://github.com/scorpionknifes)
- [Chester Cheung](https://github.com/hanyuancheung)
+19 -2
View File
@@ -3,11 +3,12 @@
[![ci](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml)
[![codecov.io](https://codecov.io/gh/open-telemetry/opentelemetry-go/coverage.svg?branch=main)](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main)
[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel)](https://pkg.go.dev/go.opentelemetry.io/otel)
[![Go Report Card](https://goreportcard.com/badge/go.opentelemetry.io/otel)](https://goreportcard.com/report/go.opentelemetry.io/otel)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/open-telemetry/opentelemetry-go/badge)](https://scorecard.dev/viewer/?uri=github.com/open-telemetry/opentelemetry-go)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9996/badge)](https://www.bestpractices.dev/projects/9996)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/opentelemetry-go.svg)](https://issues.oss-fuzz.com/issues?q=project:opentelemetry-go)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-go.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Fopen-telemetry%2Fopentelemetry-go?ref=badge_shield&issueType=license)
[![Slack](https://img.shields.io/badge/slack-@cncf/otel--go-brightgreen.svg?logo=slack)](https://slack.cncf.io/)
[![Slack](https://img.shields.io/badge/slack-@cncf/otel--go-brightgreen.svg?logo=slack)](https://cloud-native.slack.com/archives/C01NPAXACKT)
OpenTelemetry-Go is the [Go](https://golang.org/) implementation of [OpenTelemetry](https://opentelemetry.io/).
It provides a set of APIs to directly measure performance and behavior of your software and send this data to observability platforms.
@@ -18,7 +19,7 @@ It provides a set of APIs to directly measure performance and behavior of your s
|---------|--------------------|
| Traces | Stable |
| Metrics | Stable |
| Logs | Stable |
| Logs | Beta[^1] |
Progress and status specific to this repository is tracked in our
[project boards](https://github.com/open-telemetry/opentelemetry-go/projects)
@@ -28,6 +29,8 @@ and
Project versioning information and stability guarantees can be found in the
[versioning documentation](VERSIONING.md).
[^1]: https://github.com/orgs/open-telemetry/projects/43
### Compatibility
OpenTelemetry-Go ensures compatibility with the current supported versions of
@@ -52,18 +55,25 @@ Currently, this project supports the following environments.
|----------|------------|--------------|
| Ubuntu | 1.27 | amd64 |
| Ubuntu | 1.26 | amd64 |
| Ubuntu | 1.25 | amd64 |
| Ubuntu | 1.27 | 386 |
| Ubuntu | 1.26 | 386 |
| Ubuntu | 1.25 | 386 |
| Ubuntu | 1.27 | arm64 |
| Ubuntu | 1.26 | arm64 |
| Ubuntu | 1.25 | arm64 |
| macOS | 1.27 | amd64 |
| macOS | 1.26 | amd64 |
| macOS | 1.25 | amd64 |
| macOS | 1.27 | arm64 |
| macOS | 1.26 | arm64 |
| macOS | 1.25 | arm64 |
| Windows | 1.27 | amd64 |
| Windows | 1.26 | amd64 |
| Windows | 1.25 | amd64 |
| Windows | 1.27 | 386 |
| Windows | 1.26 | 386 |
| Windows | 1.25 | 386 |
While this project should work for other systems, no compatibility guarantees
are made for those systems currently.
@@ -110,3 +120,10 @@ All officially supported exporters for the OpenTelemetry project are contained i
## Contributing
See the [contributing documentation](CONTRIBUTING.md).
### Emeritus
- [Alex Kats](https://github.com/akats7), Triager
For more information about the emeritus role, see the
[community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#emeritus-maintainerapprovertriager).
-3
View File
@@ -21,7 +21,6 @@ func New() Hash {
return Hash{d: xxhash.New()}
}
// Uint64 hashes val into h, returning the updated Hash.
func (h Hash) Uint64(val uint64) Hash {
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], val)
@@ -41,12 +40,10 @@ func (h Hash) Bool(val bool) Hash { // nolint:revive // This is a hashing functi
return h.Uint64(0)
}
// Float64 hashes val into h, returning the updated Hash.
func (h Hash) Float64(val float64) Hash {
return h.Uint64(math.Float64bits(val))
}
// Int64 hashes val into h, returning the updated Hash.
func (h Hash) Int64(val int64) Hash {
return h.Uint64(uint64(val)) // nolint:gosec // Overflow doesn't matter since we are hashing.
}
-10
View File
@@ -13,16 +13,6 @@ type KeyValue struct {
Value Value
}
// String returns a string representation of KeyValue using the
// [OpenTelemetry Attribute representation for non-OTLP protocols] rules.
//
// The KeyValue is encoded as a JSON object containing a single key-value pair.
//
// [OpenTelemetry Attribute representation for non-OTLP protocols]: https://opentelemetry.io/docs/specs/otel/common/#attribute-representation-for-non-otlp
func (kv KeyValue) String() string {
return formatMap([]KeyValue{kv})
}
// Valid reports whether kv is a valid OpenTelemetry attribute.
func (kv KeyValue) Valid() bool {
return kv.Key.Defined()
-15
View File
@@ -409,21 +409,6 @@ func computeDataReflect(kvs []KeyValue) any {
return at.Interface()
}
// String returns a string representation of the Set using the
// [OpenTelemetry Attribute Collection representation for non-OTLP protocols]
// rules.
//
// The Set is encoded as a JSON object. A nil or empty Set is encoded as an
// empty JSON object.
//
// [OpenTelemetry Attribute Collection representation for non-OTLP protocols]: https://opentelemetry.io/docs/specs/otel/common/#attribute-collection-representation-for-non-otlp
func (l *Set) String() string {
if l == nil || l.hash == 0 {
return "{}"
}
return formatMapValue(l.data)
}
// MarshalJSON returns the JSON encoding of the Set.
func (l *Set) MarshalJSON() ([]byte, error) {
return json.Marshal(l.data)
+68 -167
View File
@@ -247,78 +247,10 @@ func (p properties) String() string {
return strings.Join(props, propertyDelimiter)
}
// validateMetadata validates non-empty W3C property elements without decoding
// or materializing Property values. Empty elements are accepted to preserve
// existing parsing behavior.
func validateMetadata(raw string) (string, bool) {
start := 0
for end := 0; end <= len(raw); end++ {
if end != len(raw) && raw[end] != propertyDelimiter[0] {
continue
}
if start != end {
if _, ok := parsePropertyFields(raw[start:end]); !ok {
return raw[start:end], false
}
}
start = end + 1
}
return "", true
}
// normalizeMetadata removes empty property elements while preserving the raw
// representation of all non-empty elements.
func normalizeMetadata(metadata string) string {
if metadata == "" ||
(metadata[0] != propertyDelimiter[0] &&
metadata[len(metadata)-1] != propertyDelimiter[0] &&
!strings.Contains(metadata, propertyDelimiter+propertyDelimiter)) {
return metadata
}
var normalized strings.Builder
normalized.Grow(len(metadata))
for property := range strings.SplitSeq(metadata, propertyDelimiter) {
if property == "" {
continue
}
if normalized.Len() > 0 {
_, _ = normalized.WriteString(propertyDelimiter)
}
_, _ = normalized.WriteString(property)
}
return normalized.String()
}
func propertiesFromMetadata(metadata string) properties {
if metadata == "" {
return nil
}
props := make(properties, 0, strings.Count(metadata, propertyDelimiter)+1)
for pStr := range strings.SplitSeq(metadata, propertyDelimiter) {
if pStr == "" {
continue
}
p, err := parseProperty(pStr)
if err != nil {
return nil
}
props = append(props, p)
}
return props
}
// Member is a list-member of a baggage-string as defined by the W3C Baggage
// specification.
type Member struct {
key, value string
// metadata contains the opaque W3C property suffix extracted from the wire
// without the leading semicolon. properties contains API-created
// properties. The fields are mutually exclusive.
metadata string
properties properties
// hasData indicates whether the created property contains data or not.
@@ -375,16 +307,21 @@ func newInvalidMember() Member {
return Member{}
}
// parseMember attempts to decode a Member from the passed string. Property
// metadata grammar is validated without decoding or materializing properties.
// parseMember attempts to decode a Member from the passed string. It returns
// an error if the input is invalid according to the W3C Baggage
// specification.
func parseMember(member string) (Member, error) {
var metadata string
keyValue, rawMetadata, found := strings.Cut(member, propertyDelimiter)
var props properties
keyValue, properties, found := strings.Cut(member, propertyDelimiter)
if found {
if invalid, ok := validateMetadata(rawMetadata); !ok {
return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidProperty, invalid)
// Parse the member properties.
for pStr := range strings.SplitSeq(properties, propertyDelimiter) {
p, err := parseProperty(pStr)
if err != nil {
return newInvalidMember(), err
}
props = append(props, p)
}
metadata = normalizeMetadata(rawMetadata)
}
// Parse the member key/value pair.
@@ -412,7 +349,7 @@ func parseMember(member string) (Member, error) {
}
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
return Member{key: key, value: value, metadata: metadata, hasData: true}, nil
return Member{key: key, value: value, properties: props, hasData: true}, nil
}
// replaceInvalidUTF8Sequences replaces invalid UTF-8 sequences with '�'.
@@ -462,14 +399,10 @@ func (m Member) Key() string { return m.key }
func (m Member) Value() string { return m.value }
// Properties returns a copy of the Member properties.
func (m Member) Properties() []Property {
if m.metadata != "" {
return propertiesFromMetadata(m.metadata)
}
return m.properties.Copy()
}
func (m Member) Properties() []Property { return m.properties.Copy() }
// String encodes Member into a baggage header string.
// String encodes Member into a header string compliant with the W3C Baggage
// specification.
// It would return empty string if the key is invalid with the W3C Baggage
// specification. This could happen for a UTF-8 key, as it may contain
// invalid characters.
@@ -480,31 +413,12 @@ func (m Member) String() string {
}
s := m.key + keyValueDelimiter + valueEscape(m.value)
if m.metadata != "" {
s += propertyDelimiter + m.metadata
} else if len(m.properties) > 0 {
if len(m.properties) > 0 {
s += propertyDelimiter + m.properties.String()
}
return s
}
func memberFromItem(key string, item baggage.Item) Member {
return Member{
key: key,
value: item.Value(),
metadata: item.Metadata(),
properties: fromInternalProperties(item.Properties()),
hasData: true,
}
}
func itemFromMember(member Member) baggage.Item {
if member.metadata != "" {
return baggage.NewItemWithMetadata(member.value, member.metadata)
}
return baggage.NewItemWithProperties(member.value, member.properties.asInternal())
}
// Baggage is a list of baggage members representing the baggage-string as
// defined by the W3C Baggage specification.
type Baggage struct { //nolint:golint
@@ -530,7 +444,10 @@ func New(members ...Member) (Baggage, error) {
return Baggage{}, errInvalidMember
}
// OpenTelemetry resolves duplicates by last-one-wins.
b[m.key] = itemFromMember(m)
b[m.key] = baggage.Item{
Value: m.value,
Properties: m.properties.asInternal(),
}
}
var truncateErr error
@@ -550,7 +467,11 @@ func New(members ...Member) (Baggage, error) {
totalBytes := 0
first := true
for k := range b {
m := memberFromItem(k, b[k])
m := Member{
key: k,
value: b[k].Value,
properties: fromInternalProperties(b[k].Properties),
}
memberSize := len(m.String())
if !first {
memberSize++ // comma separator
@@ -642,7 +563,10 @@ func Parse(bStr string) (Baggage, error) {
}
// OpenTelemetry resolves duplicates by last-one-wins.
b[m.key] = itemFromMember(m)
b[m.key] = baggage.Item{
Value: m.value,
Properties: m.properties.asInternal(),
}
sizes[m.key] = memberBytes
totalBytes = newTotalBytes
}
@@ -673,7 +597,12 @@ func (b Baggage) Member(key string) Member {
return newInvalidMember()
}
return memberFromItem(key, v)
return Member{
key: key,
value: v.Value,
properties: fromInternalProperties(v.Properties),
hasData: true,
}
}
// Members returns all the baggage list-members.
@@ -688,7 +617,12 @@ func (b Baggage) Members() []Member {
members := make([]Member, 0, len(b.list))
for k, v := range b.list {
members = append(members, memberFromItem(k, v))
members = append(members, Member{
key: k,
value: v.Value,
properties: fromInternalProperties(v.Properties),
hasData: true,
})
}
return members
}
@@ -718,7 +652,10 @@ func (b Baggage) SetMember(member Member) (Baggage, error) {
list[k] = v
}
list[member.key] = itemFromMember(member)
list[member.key] = baggage.Item{
Value: member.value,
Properties: member.properties.asInternal(),
}
return Baggage{list: list}, nil
}
@@ -755,7 +692,11 @@ func (b Baggage) Len() int {
func (b Baggage) String() string {
members := make([]string, 0, len(b.list))
for k, v := range b.list {
s := memberFromItem(k, v).String()
s := Member{
key: k,
value: v.Value,
properties: fromInternalProperties(v.Properties),
}.String()
// Ignored empty members.
if s != "" {
@@ -765,14 +706,9 @@ func (b Baggage) String() string {
return strings.Join(members, listDelimiter)
}
type propertyFields struct {
key, rawValue string
hasValue bool
}
// parsePropertyFields validates and locates a property's fields without
// decoding or allocating them.
func parsePropertyFields(s string) (fields propertyFields, ok bool) {
// parsePropertyInternal attempts to decode a Property from the passed string.
// It follows the spec at https://www.w3.org/TR/baggage/#definition.
func parsePropertyInternal(s string) (p Property, ok bool) {
// For the entire function we will use " key = value " as an example.
// Attempting to parse the key.
// First skip spaces at the beginning "< >key = value " (they could be empty).
@@ -791,7 +727,7 @@ func parsePropertyFields(s string) (fields propertyFields, ok bool) {
// If we couldn't find any valid key character,
// it means the key is either empty or invalid.
if keyStart == keyEnd {
return fields, ok
return p, ok
}
// Skip spaces after the key: " key< >= value ".
@@ -799,14 +735,15 @@ func parsePropertyFields(s string) (fields propertyFields, ok bool) {
if index == len(s) {
// A key can have no value, like: " key ".
fields.key = s[keyStart:keyEnd]
return fields, true
ok = true
p.key = s[keyStart:keyEnd]
return p, ok
}
// If we have not reached the end and we can't find the '=' delimiter,
// it means the property is invalid.
if s[index] != keyValueDelimiter[0] {
return fields, ok
return p, ok
}
// Attempting to parse the value.
@@ -832,59 +769,23 @@ func parsePropertyFields(s string) (fields propertyFields, ok bool) {
// we have not reached the end, it means the property is
// invalid, something like: " key = value value1".
if index != len(s) {
return fields, ok
}
rawVal := s[valueStart:valueEnd]
if !validPercentEncoding(rawVal) {
return fields, ok
}
fields.key = s[keyStart:keyEnd]
fields.rawValue = rawVal
fields.hasValue = true
return fields, true
}
func validPercentEncoding(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] != '%' {
continue
}
if i+2 >= len(s) || !isHex(s[i+1]) || !isHex(s[i+2]) {
return false
}
i += 2
}
return true
}
func isHex(c byte) bool {
return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
}
// parsePropertyInternal attempts to decode a Property from the passed string.
// It follows the spec at https://www.w3.org/TR/baggage/#definition.
func parsePropertyInternal(s string) (p Property, ok bool) {
fields, ok := parsePropertyFields(s)
if !ok {
return p, false
}
if !fields.hasValue {
p.key = fields.key
return p, true
return p, ok
}
// Decode a percent-encoded value.
unescapeVal, err := url.PathUnescape(fields.rawValue)
rawVal := s[valueStart:valueEnd]
unescapeVal, err := url.PathUnescape(rawVal)
if err != nil {
return p, false
return p, ok
}
value := replaceInvalidUTF8Sequences(len(fields.rawValue), unescapeVal)
value := replaceInvalidUTF8Sequences(len(rawVal), unescapeVal)
p.key = fields.key
ok = true
p.key = s[keyStart:keyEnd]
p.hasValue = true
p.value = value
return p, true
return p, ok
}
func skipSpace(s string, offset int) int {
+1 -1
View File
@@ -32,7 +32,7 @@ const (
maxCode = 3
)
// Code is a 32-bit representation of a status state.
// Code is an 32-bit representation of a status state.
type Code uint32
var codeToStr = map[Code]string{
+1 -1
View File
@@ -1,4 +1,4 @@
# This is a renovate-friendly source of Docker images.
FROM python:3.13.6-slim-bullseye@sha256:e98b521460ee75bca92175c16247bdf7275637a8faaeb2bcfa19d879ae5c4b9a AS python
FROM otel/weaver:v0.26.1@sha256:9094862c0ab261bdbcb079bb981f9a573b3659b130a6d2ab8616eca6ba37aaec AS weaver
FROM otel/weaver:v0.25.1@sha256:9ad46ca9cd4fa5974b121f886aa3e9946a8ef8ea905001a96c018d21f9db87ca AS weaver
FROM avtodev/markdown-lint:v1@sha256:6aeedc2f49138ce7a1cd0adffc1b1c0321b841dc2102408967d9301c031949ee AS markdown
@@ -18,8 +18,8 @@ package internal
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/envconfig.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig\"}" --out=oconf/envconfig.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/envconfig_test.go.tmpl "--data={}" --out=oconf/envconfig_test.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/options.go.tmpl "--data={\"isHTTP\": false, \"retryImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry\"}" --out=oconf/options.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/options_test.go.tmpl "--data={\"isHTTP\": false, \"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig\"}" --out=oconf/options_test.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/options.go.tmpl "--data={\"retryImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/retry\"}" --out=oconf/options.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/options_test.go.tmpl "--data={\"envconfigImportPath\": \"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/envconfig\"}" --out=oconf/options_test.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/optiontypes.go.tmpl "--data={}" --out=oconf/optiontypes.go
//go:generate gotmpl --body=../../../../../internal/shared/otlp/otlpmetric/oconf/tls.go.tmpl "--data={}" --out=oconf/tls.go
@@ -121,22 +121,11 @@ func withEndpointForGRPC(u *url.URL) func(cfg Config) Config {
return func(cfg Config) Config {
// For OTLP/gRPC endpoints, this is the target to which the
// exporter is going to send telemetry.
cfg.Metrics.Endpoint = grpcEndpoint(u)
cfg.Metrics.Endpoint = path.Join(u.Host, u.Path)
return cfg
}
}
func grpcEndpoint(u *url.URL) string {
switch strings.ToLower(u.Scheme) {
case "http", "https":
return u.Host
case "":
return path.Join(u.Host, u.Path)
default:
return u.String()
}
}
// WithEnvCompression retrieves the specified config and passes it to ConfigFn as a Compression.
func WithEnvCompression(n string, fn func(Compression)) func(e *envconfig.EnvOptionsReader) {
return func(e *envconfig.EnvOptionsReader) {
@@ -153,7 +142,7 @@ func WithEnvCompression(n string, fn func(Compression)) func(e *envconfig.EnvOpt
func withEndpointScheme(u *url.URL) GenericOption {
switch strings.ToLower(u.Scheme) {
case "http", "unix", "unix-abstract":
case "http", "unix":
return WithInsecure()
default:
return WithSecure()

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