mirror of
https://github.com/docker/cli.git
synced 2026-08-26 02:24:12 -05:00
Compare commits
@@ -66,7 +66,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
set: |
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
fi
|
||||
-
|
||||
name: Upload artifacts
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: /tmp/out/*
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_CLIBIN_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_CLIBIN_TOKEN }}
|
||||
@@ -125,7 +125,7 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
-
|
||||
name: Build and push image
|
||||
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
with:
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
||||
-
|
||||
name: Build
|
||||
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
with:
|
||||
targets: plugins-cross
|
||||
set: |
|
||||
|
||||
@@ -63,18 +63,18 @@ jobs:
|
||||
name: Update Go
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
with:
|
||||
go-version: "1.26.1"
|
||||
go-version: "1.26.2"
|
||||
cache: false
|
||||
-
|
||||
name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
|
||||
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
|
||||
with:
|
||||
languages: go
|
||||
-
|
||||
name: Autobuild
|
||||
uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
|
||||
uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
|
||||
-
|
||||
name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
|
||||
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
|
||||
with:
|
||||
category: "/language:go"
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
with:
|
||||
targets: test-coverage
|
||||
-
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
with:
|
||||
go-version: "1.26.1"
|
||||
go-version: "1.26.2"
|
||||
cache: false
|
||||
-
|
||||
name: Test
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
name: validate-milestone
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, milestoned, demilestoned, edited]
|
||||
|
||||
jobs:
|
||||
validate-milestone:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
sparse-checkout: VERSION
|
||||
|
||||
- name: Validate milestone matches VERSION
|
||||
run: |
|
||||
expected=$(cat VERSION)
|
||||
milestone="${{ github.event.pull_request.milestone.title }}"
|
||||
|
||||
if [[ -z "$milestone" ]]; then
|
||||
echo "::error::PR must have a milestone set (expected: $expected)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$milestone" != "$expected" ]]; then
|
||||
echo "::error::Milestone '$milestone' does not match VERSION '$expected'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Milestone: $milestone ✓"
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
steps:
|
||||
-
|
||||
name: Run
|
||||
uses: docker/bake-action@82490499d2e5613fcead7e128237ef0b0ea210f7 # v7
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
with:
|
||||
go-version: "1.26.1"
|
||||
go-version: "1.26.2"
|
||||
cache: false
|
||||
-
|
||||
name: Run gocompat check
|
||||
|
||||
+8
-1
@@ -5,7 +5,7 @@ run:
|
||||
# which causes it to fallback to go1.17 semantics.
|
||||
#
|
||||
# TODO(thaJeztah): update "usetesting" settings to enable go1.24 features once our minimum version is go1.24
|
||||
go: "1.26.1"
|
||||
go: "1.26.2"
|
||||
|
||||
timeout: 5m
|
||||
|
||||
@@ -110,8 +110,15 @@ linters:
|
||||
excludes:
|
||||
- G104 # G104: Errors unhandled; (TODO: reduce unhandled errors, or explicitly ignore)
|
||||
- G115 # G115: integer overflow conversion; (TODO: verify these: https://github.com/docker/cli/issues/5584)
|
||||
- G117 # G117: Exported struct field matches secret pattern (false positives for legitimate field names)
|
||||
- G118 # G118: Goroutine uses context.Background/TODO while request-scoped context is available (TODO: evaluate these)
|
||||
- G122 # G122: Filesystem operation in filepath.Walk/WalkDir callback uses race-prone path (TODO: evaluate these)
|
||||
- G306 # G306: Expect WriteFile permissions to be 0600 or less (too restrictive; also flags "0o644" permissions)
|
||||
- G307 # G307: Deferring unsafe method "*os.File" on type "Close" (also EXC0008); (TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close")
|
||||
- G702 # G702: Command injection via taint analysis (TODO: evaluate these)
|
||||
- G703 # G703: Path traversal via taint analysis (TODO: evaluate these)
|
||||
- G704 # G704: SSRF via taint analysis (TODO: evaluate these)
|
||||
- G705 # G705: XSS via taint analysis (TODO: evaluate these)
|
||||
|
||||
govet:
|
||||
enable:
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ ARG BASE_VARIANT=alpine
|
||||
ARG ALPINE_VERSION=3.23
|
||||
ARG BASE_DEBIAN_DISTRO=bookworm
|
||||
|
||||
ARG GO_VERSION=1.26.1
|
||||
ARG GO_VERSION=1.26.2
|
||||
|
||||
# XX_VERSION specifies the version of the xx utility to use.
|
||||
# It must be a valid tag in the docker.io/tonistiigi/xx image repository.
|
||||
@@ -25,12 +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.31.1
|
||||
ARG BUILDX_VERSION=0.33.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.1.0
|
||||
ARG COMPOSE_VERSION=v5.1.3
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
|
||||
@@ -177,9 +177,8 @@ func TestGetPluginDirs(t *testing.T) {
|
||||
pluginDirs := getPluginDirs(cli.ConfigFile())
|
||||
assert.Equal(t, strings.Join(expected, ":"), strings.Join(pluginDirs, ":"))
|
||||
|
||||
extras := []string{
|
||||
"foo", "bar", "baz",
|
||||
}
|
||||
extras := make([]string, 0, 3+len(expected))
|
||||
extras = append(extras, "foo", "bar", "baz")
|
||||
expected = append(extras, expected...)
|
||||
cli.SetConfigFile(&configfile.ConfigFile{
|
||||
CLIPluginsExtraDirs: extras,
|
||||
|
||||
+3
-2
@@ -566,11 +566,12 @@ type ServerInfo struct {
|
||||
// It applies by default the standard streams, and the content trust from
|
||||
// environment.
|
||||
func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
|
||||
defaultOps := []CLIOption{
|
||||
defaultOps := make([]CLIOption, 0, 3+len(ops))
|
||||
defaultOps = append(defaultOps,
|
||||
WithDefaultContextStoreConfig(),
|
||||
WithStandardStreams(),
|
||||
WithUserAgent(UserAgent()),
|
||||
}
|
||||
)
|
||||
ops = append(defaultOps, ops...)
|
||||
|
||||
cli := &DockerCli{baseCtx: context.Background()}
|
||||
|
||||
+23
-23
@@ -5,19 +5,19 @@ go 1.25.0
|
||||
require (
|
||||
github.com/containerd/errdefs v1.0.0
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/cli v29.3.1+incompatible
|
||||
github.com/docker/cli v29.4.0+incompatible
|
||||
github.com/docker/cli-docs-tool v0.11.0
|
||||
github.com/docker/distribution v2.8.3+incompatible
|
||||
github.com/docker/go-connections v0.6.0
|
||||
github.com/docker/go-connections v0.7.0
|
||||
github.com/fvbommel/sortorder v1.1.0
|
||||
github.com/moby/moby/api v1.54.0
|
||||
github.com/moby/moby/client v0.3.0
|
||||
github.com/moby/moby/api v1.54.2
|
||||
github.com/moby/moby/client v0.4.1
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a
|
||||
go.opentelemetry.io/otel v1.42.0
|
||||
go.opentelemetry.io/otel v1.43.0
|
||||
gotest.tools/v3 v3.5.2
|
||||
)
|
||||
|
||||
@@ -41,7 +41,7 @@ require (
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.20 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.2 // indirect
|
||||
@@ -56,22 +56,22 @@ require (
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.42.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/term v0.41.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/term v0.42.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/grpc v1.80.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
||||
+48
-48
@@ -47,8 +47,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v29.3.1+incompatible h1:M04FDj2TRehDacrosh7Vlkgc7AuQoWloQkf1PA5hmoI=
|
||||
github.com/docker/cli v29.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM=
|
||||
github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli-docs-tool v0.11.0 h1:7d8QARFb7QEobizqxmEM7fOteZEHwH/zWgHQtHZEcfE=
|
||||
github.com/docker/cli-docs-tool v0.11.0/go.mod h1:ma8BKiisUo8D6W05XEYIh3oa1UbgrZhi1nowyKFJa8Q=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
@@ -59,8 +59,8 @@ github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||
github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
|
||||
github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
@@ -108,8 +108,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
@@ -148,10 +148,10 @@ github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KH
|
||||
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/moby/api v1.54.0 h1:7kbUgyiKcoBhm0UrWbdrMs7RX8dnwzURKVbZGy2GnL0=
|
||||
github.com/moby/moby/api v1.54.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
|
||||
github.com/moby/moby/client v0.3.0 h1:UUGL5okry+Aomj3WhGt9Aigl3ZOxZGqR7XPo+RLPlKs=
|
||||
github.com/moby/moby/client v0.3.0/go.mod h1:HJgFbJRvogDQjbM8fqc1MCEm4mIAGMLjXbgwoZp6jCQ=
|
||||
github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg=
|
||||
github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
|
||||
github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY=
|
||||
github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ=
|
||||
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/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
@@ -237,26 +237,26 @@ github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a h1:tlJ
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a/go.mod h1:Y94A6rPp2OwNfP/7vmf8O2xx2IykP8pPXQ1DLouGnEw=
|
||||
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.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0=
|
||||
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
|
||||
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0 h1:NOyNnS19BF2SUDApbOKbDtWZ0IK7b8FJ2uAGdIWOGb0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.40.0/go.mod h1:VL6EgVikRLcJa9ftukrHu/ZkkhFBSo1lzvdBC9CF1ss=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
|
||||
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
|
||||
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
|
||||
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
@@ -265,14 +265,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -285,24 +285,24 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
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-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
|
||||
@@ -4,13 +4,13 @@ package registry
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ func loadTLSConfig(ctx context.Context, directory string, tlsConfig *tls.Config)
|
||||
switch filepath.Ext(f.Name()) {
|
||||
case ".crt":
|
||||
if tlsConfig.RootCAs == nil {
|
||||
systemPool, err := tlsconfig.SystemCertPool()
|
||||
systemPool, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
return invalidParam(fmt.Errorf("unable to get system cert pool: %w", err))
|
||||
}
|
||||
|
||||
@@ -1929,7 +1929,6 @@ _docker_container_run_and_create() {
|
||||
--ip
|
||||
--ip6
|
||||
--ipc
|
||||
--kernel-memory
|
||||
--label-file
|
||||
--label -l
|
||||
--link
|
||||
@@ -2310,7 +2309,6 @@ _docker_container_update() {
|
||||
--cpuset-cpus
|
||||
--cpuset-mems
|
||||
--cpu-shares -c
|
||||
--kernel-memory
|
||||
--memory -m
|
||||
--memory-reservation
|
||||
--memory-swap
|
||||
|
||||
@@ -226,7 +226,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ip -d 'IPv4
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ip6 -d 'IPv6 address (e.g., 2001:db8::33)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ipc -d 'IPC mode to use'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l isolation -d 'Container isolation technology'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l kernel-memory -d 'Kernel memory limit'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s l -l label -d 'Set meta data on a container'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l label-file -d 'Read in a line delimited file of labels'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add link to another container'
|
||||
|
||||
@@ -675,7 +675,6 @@ __docker_container_subcommand() {
|
||||
"($help)--cpu-rt-runtime=[Limit the CPU real-time runtime]:CPU real-time runtime in microseconds: "
|
||||
"($help)--cpuset-cpus=[CPUs in which to allow execution]:CPUs: "
|
||||
"($help)--cpuset-mems=[MEMs in which to allow execution]:MEMs: "
|
||||
"($help)--kernel-memory=[Kernel memory limit in bytes]:Memory limit: "
|
||||
"($help -m --memory)"{-m=,--memory=}"[Memory limit]:Memory limit: "
|
||||
"($help)--memory-reservation=[Memory soft limit]:Memory limit: "
|
||||
"($help)--memory-swap=[Total memory limit with swap]:Memory limit: "
|
||||
@@ -938,11 +937,7 @@ __docker_container_subcommand() {
|
||||
"($help -)*: :->values" && ret=0
|
||||
case $state in
|
||||
(values)
|
||||
if [[ ${words[(r)--kernel-memory*]} = (--kernel-memory*) ]]; then
|
||||
__docker_complete_stopped_containers && ret=0
|
||||
else
|
||||
__docker_complete_containers && ret=0
|
||||
fi
|
||||
__docker_complete_containers && ret=0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ CACHE_VOLUME_NAME := docker-cli-dev-cache
|
||||
ifeq ($(DOCKER_CLI_GO_BUILD_CACHE),y)
|
||||
DOCKER_CLI_MOUNTS += -v "$(CACHE_VOLUME_NAME):/root/.cache/go-build"
|
||||
endif
|
||||
VERSION = $(shell cat VERSION)
|
||||
VERSION ?= $(shell cat VERSION)-dev
|
||||
ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT -e PLATFORM -e TESTFLAGS -e TESTDIRS -e GOOS -e GOARCH -e GOARM -e ENGINE_VERSION
|
||||
|
||||
# Some Dockerfiles use features that are only supported with BuildKit enabled
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.26.1
|
||||
ARG GO_VERSION=1.26.2
|
||||
|
||||
# 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
|
||||
@@ -10,7 +10,7 @@ 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.31.1
|
||||
ARG BUILDX_VERSION=0.33.0
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.26.1
|
||||
ARG GO_VERSION=1.26.2
|
||||
|
||||
# ALPINE_VERSION sets the version of the alpine base image to use, including for the golang image.
|
||||
# It must be a supported tag in the docker.io/library/alpine image repository
|
||||
# that's also available as alpine image variant for the Golang version used.
|
||||
ARG ALPINE_VERSION=3.23
|
||||
# GOLANGCI_LINT_VERSION sets the version of the golangci/golangci-lint image to use.
|
||||
ARG GOLANGCI_LINT_VERSION=v2.9.0
|
||||
ARG GOLANGCI_LINT_VERSION=v2.10.1
|
||||
|
||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.26.1
|
||||
ARG GO_VERSION=1.26.2
|
||||
|
||||
# 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
|
||||
|
||||
@@ -10,6 +10,14 @@ This document describes the Docker Engine plugins generally available in Docker
|
||||
Engine. To view information on plugins managed by Docker,
|
||||
refer to [Docker Engine plugin system](_index.md).
|
||||
|
||||
> [!NOTE]
|
||||
> Legacy plugins are superseded by Docker Engine's managed plugin system.
|
||||
> For plugins installed and managed by Docker, use
|
||||
> [`docker plugin install`](https://docs.docker.com/reference/cli/docker/plugin/install/)
|
||||
> and the [Docker Engine plugin system](_index.md). The third-party plugins
|
||||
> listed on this page are provided for historical reference, and archived
|
||||
> projects are marked accordingly.
|
||||
|
||||
You can extend the capabilities of the Docker Engine by loading third-party
|
||||
plugins. This page explains the types of plugins and provides links to several
|
||||
volume and network plugins for Docker.
|
||||
@@ -30,7 +38,8 @@ Follow the instructions in the plugin's documentation.
|
||||
|
||||
## Finding a plugin
|
||||
|
||||
The sections below provide an overview of available third-party plugins.
|
||||
The sections below provide an overview of third-party plugins that use the
|
||||
legacy plugin model.
|
||||
|
||||
### Network plugins
|
||||
|
||||
@@ -44,22 +53,21 @@ The sections below provide an overview of available third-party plugins.
|
||||
|
||||
| Plugin | Description |
|
||||
|:---------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Azure File Storage plugin](https://github.com/Azure/azurefile-dockervolumedriver) | Lets you mount Microsoft [Azure File Storage](https://azure.microsoft.com/blog/azure-file-storage-now-generally-available/) shares to Docker containers as volumes using the SMB 3.0 protocol. [Learn more](https://azure.microsoft.com/blog/persistent-docker-volumes-with-azure-file-storage/). |
|
||||
| [Azure File Storage plugin](https://github.com/Azure/azurefile-dockervolumedriver) (archived) | Lets you mount Microsoft [Azure File Storage](https://azure.microsoft.com/blog/azure-file-storage-now-generally-available/) shares to Docker containers as volumes using the SMB 3.0 protocol. [Learn more](https://azure.microsoft.com/blog/persistent-docker-volumes-with-azure-file-storage/). |
|
||||
| [BeeGFS Volume Plugin](https://github.com/RedCoolBeans/docker-volume-beegfs) | An open source volume plugin to create persistent volumes in a BeeGFS parallel file system. |
|
||||
| [Blockbridge plugin](https://github.com/blockbridge/blockbridge-docker-volume) | A volume plugin that provides access to an extensible set of container-based persistent storage options. It supports single and multi-host Docker environments with features that include tenant isolation, automated provisioning, encryption, secure deletion, snapshots and QoS. |
|
||||
| [Contiv Volume Plugin](https://github.com/contiv/volplugin) | An open source volume plugin that provides multi-tenant, persistent, distributed storage with intent based consumption. It has support for Ceph and NFS. |
|
||||
| [Convoy plugin](https://github.com/rancher/convoy) | A volume plugin for a variety of storage back-ends including device mapper and NFS. It's a simple standalone executable written in Go and provides the framework to support vendor-specific extensions such as snapshots, backups and restore. |
|
||||
| [Convoy plugin](https://github.com/rancher/convoy) (archived) | A volume plugin for a variety of storage back-ends including device mapper and NFS. It's a simple standalone executable written in Go and provides the framework to support vendor-specific extensions such as snapshots, backups and restore. |
|
||||
| [DigitalOcean Block Storage plugin](https://github.com/omallo/docker-volume-plugin-dostorage) | Integrates DigitalOcean's [block storage solution](https://www.digitalocean.com/products/storage/) into the Docker ecosystem by automatically attaching a given block storage volume to a DigitalOcean droplet and making the contents of the volume available to Docker containers running on that droplet. |
|
||||
| [DRBD plugin](https://www.drbd.org/en/supported-projects/docker) | A volume plugin that provides highly available storage replicated by [DRBD](https://www.drbd.org). Data written to the docker volume is replicated in a cluster of DRBD nodes. |
|
||||
| [Flocker plugin](https://github.com/ScatterHQ/flocker) | A volume plugin that provides multi-host portable volumes for Docker, enabling you to run databases and other stateful containers and move them around across a cluster of machines. |
|
||||
| [Fuxi Volume Plugin](https://github.com/openstack/fuxi) | A volume plugin that is developed as part of the OpenStack Kuryr project and implements the Docker volume plugin API by utilizing Cinder, the OpenStack block storage service. |
|
||||
| [gce-docker plugin](https://github.com/mcuadros/gce-docker) | A volume plugin able to attach, format and mount Google Compute [persistent-disks](https://cloud.google.com/compute/docs/disks/persistent-disks). |
|
||||
| [GlusterFS plugin](https://github.com/calavera/docker-volume-glusterfs) | A volume plugin that provides multi-host volumes management for Docker using GlusterFS. |
|
||||
| [Flocker plugin](https://github.com/ScatterHQ/flocker) (archived) | A volume plugin that provides multi-host portable volumes for Docker, enabling you to run databases and other stateful containers and move them around across a cluster of machines. |
|
||||
| [Fuxi Volume Plugin](https://github.com/openstack-archive/fuxi) (archived) | A volume plugin that is developed as part of the OpenStack Kuryr project and implements the Docker volume plugin API by utilizing Cinder, the OpenStack block storage service. |
|
||||
| [gce-docker plugin](https://github.com/mcuadros/gce-docker) (archived) | A volume plugin able to attach, format and mount Google Compute [persistent-disks](https://cloud.google.com/compute/docs/disks/persistent-disks). |
|
||||
| [GlusterFS plugin](https://github.com/calavera/docker-volume-glusterfs) (archived) | A volume plugin that provides multi-host volumes management for Docker using GlusterFS. |
|
||||
| [Horcrux Volume Plugin](https://github.com/muthu-r/horcrux) | A volume plugin that allows on-demand, version controlled access to your data. Horcrux is an open-source plugin, written in Go, and supports SCP, [Minio](https://www.minio.io) and Amazon S3. |
|
||||
| [HPE 3Par Volume Plugin](https://github.com/hpe-storage/python-hpedockerplugin/) | A volume plugin that supports HPE 3Par and StoreVirtual iSCSI storage arrays. |
|
||||
| [Infinit volume plugin](https://infinit.sh/documentation/docker/volume-plugin) | A volume plugin that makes it easy to mount and manage Infinit volumes using Docker. |
|
||||
| [IPFS Volume Plugin](https://github.com/vdemeester/docker-volume-ipfs) | An open source volume plugin that allows using an [ipfs](https://ipfs.io/) filesystem as a volume. |
|
||||
| [Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) | A plugin that provides credentials and secret management using Keywhiz as a central repository. |
|
||||
| [IPFS Volume Plugin](https://github.com/vdemeester/docker-volume-ipfs) (archived) | An open source volume plugin that allows using an [ipfs](https://ipfs.io/) filesystem as a volume. |
|
||||
| [Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) (archived) | A plugin that provides credentials and secret management using Keywhiz as a central repository. |
|
||||
| [Linode Volume Plugin](https://github.com/linode/docker-volume-linode) | A plugin that adds the ability to manage Linode Block Storage as Docker Volumes from within a Linode. |
|
||||
| [Local Persist Plugin](https://github.com/CWSpear/local-persist) | A volume plugin that extends the default `local` driver's functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to *always persist*, even if the volume is removed via `docker volume rm`. |
|
||||
| [NetApp Plugin](https://github.com/NetApp/netappdvp) (nDVP) | A volume plugin that provides direct integration with the Docker ecosystem for the NetApp storage portfolio. The nDVP package supports the provisioning and management of storage resources from the storage platform to Docker hosts, with a robust framework for adding additional platforms in the future. |
|
||||
|
||||
@@ -37,11 +37,6 @@ resources from their Docker host. With a single command, you can place
|
||||
limits on a single container or on many. To specify more than one container,
|
||||
provide space-separated list of container names or IDs.
|
||||
|
||||
With the exception of the `--kernel-memory` option, you can specify these
|
||||
options on a running or a stopped container. On kernel version older than
|
||||
4.6, you can only update `--kernel-memory` on a stopped container or on
|
||||
a running container with kernel memory initialized.
|
||||
|
||||
> [!WARNING]
|
||||
> The `docker update` and `docker container update` commands are not supported
|
||||
> for Windows containers.
|
||||
@@ -69,42 +64,6 @@ To update multiple resource configurations for multiple containers:
|
||||
$ docker update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
|
||||
```
|
||||
|
||||
### <a name="kernel-memory"></a> Update a container's kernel memory constraints (--kernel-memory)
|
||||
|
||||
You can update a container's kernel memory limit using the `--kernel-memory`
|
||||
option. On kernel version older than 4.6, this option can be updated on a
|
||||
running container only if the container was started with `--kernel-memory`.
|
||||
If the container was started without `--kernel-memory` you need to stop
|
||||
the container before updating kernel memory.
|
||||
|
||||
> [!NOTE]
|
||||
> The `--kernel-memory` option has been deprecated since Docker 20.10.
|
||||
|
||||
For example, if you started a container with this command:
|
||||
|
||||
```console
|
||||
$ docker run -dit --name test --kernel-memory 50M ubuntu bash
|
||||
```
|
||||
|
||||
You can update kernel memory while the container is running:
|
||||
|
||||
```console
|
||||
$ docker update --kernel-memory 80M test
|
||||
```
|
||||
|
||||
If you started a container without kernel memory initialized:
|
||||
|
||||
```console
|
||||
$ docker run -dit --name test2 --memory 300M ubuntu bash
|
||||
```
|
||||
|
||||
Update kernel memory of running container `test2` will fail. You need to stop
|
||||
the container before updating the `--kernel-memory` setting. The next time you
|
||||
start it, the container uses the new value.
|
||||
|
||||
Kernel version newer than (include) 4.6 does not have this limitation, you
|
||||
can use `--kernel-memory` the same way as other options.
|
||||
|
||||
### <a name="restart"></a> Update a container's restart policy (--restart)
|
||||
|
||||
You can change a container's restart policy on a running container. The new
|
||||
|
||||
@@ -334,7 +334,6 @@ container:
|
||||
| `-m`, `--memory=""` | Memory limit (format: `<number>[<unit>]`). Number is a positive integer. Unit can be one of `b`, `k`, `m`, or `g`. Minimum is 6M. |
|
||||
| `--memory-swap=""` | Total memory limit (memory + swap, format: `<number>[<unit>]`). Number is a positive integer. Unit can be one of `b`, `k`, `m`, or `g`. |
|
||||
| `--memory-reservation=""` | Memory soft limit (format: `<number>[<unit>]`). Number is a positive integer. Unit can be one of `b`, `k`, `m`, or `g`. |
|
||||
| `--kernel-memory=""` | Kernel memory limit (format: `<number>[<unit>]`). Number is a positive integer. Unit can be one of `b`, `k`, `m`, or `g`. Minimum is 4M. |
|
||||
| `-c`, `--cpu-shares=0` | CPU shares (relative weight) |
|
||||
| `--cpus=0.000` | Number of CPUs. Number is a fractional number. 0.000 means no limit. |
|
||||
| `--cpu-period=0` | Limit the CPU CFS (Completely Fair Scheduler) period |
|
||||
@@ -500,80 +499,6 @@ parameter can be changed to select the priority of which containers will
|
||||
be killed when the system is out of memory, with negative scores making them
|
||||
less likely to be killed, and positive scores more likely.
|
||||
|
||||
### Kernel memory constraints
|
||||
|
||||
Kernel memory is fundamentally different than user memory as kernel memory can't
|
||||
be swapped out. The inability to swap makes it possible for the container to
|
||||
block system services by consuming too much kernel memory. Kernel memory includes:
|
||||
|
||||
- stack pages
|
||||
- slab pages
|
||||
- sockets memory pressure
|
||||
- tcp memory pressure
|
||||
|
||||
You can setup kernel memory limit to constrain these kinds of memory. For example,
|
||||
every process consumes some stack pages. By limiting kernel memory, you can
|
||||
prevent new processes from being created when the kernel memory usage is too high.
|
||||
|
||||
Kernel memory is never completely independent of user memory. Instead, you limit
|
||||
kernel memory in the context of the user memory limit. Assume "U" is the user memory
|
||||
limit and "K" the kernel limit. There are three possible ways to set limits:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Option</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="no-wrap"><strong>U != 0, K = inf</strong> (default)</td>
|
||||
<td>
|
||||
This is the standard memory limitation mechanism already present before using
|
||||
kernel memory. Kernel memory is completely ignored.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="no-wrap"><strong>U != 0, K < U</strong></td>
|
||||
<td>
|
||||
Kernel memory is a subset of the user memory. This setup is useful in
|
||||
deployments where the total amount of memory per-cgroup is overcommitted.
|
||||
Overcommitting kernel memory limits is definitely not recommended, since the
|
||||
box can still run out of non-reclaimable memory.
|
||||
In this case, you can configure K so that the sum of all groups is
|
||||
never greater than the total memory. Then, freely set U at the expense of
|
||||
the system's service quality.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="no-wrap"><strong>U != 0, K > U</strong></td>
|
||||
<td>
|
||||
Since kernel memory charges are also fed to the user counter and reclamation
|
||||
is triggered for the container for both kinds of memory. This configuration
|
||||
gives the admin a unified view of memory. It is also useful for people
|
||||
who just want to track kernel memory usage.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Examples:
|
||||
|
||||
```console
|
||||
$ docker run -it -m 500M --kernel-memory 50M ubuntu:24.04 /bin/bash
|
||||
```
|
||||
|
||||
We set memory and kernel memory, so the processes in the container can use
|
||||
500M memory in total, in this 500M memory, it can be 50M kernel memory tops.
|
||||
|
||||
```console
|
||||
$ docker run -it --kernel-memory 50M ubuntu:24.04 /bin/bash
|
||||
```
|
||||
|
||||
We set kernel memory without **-m**, so the processes in the container can
|
||||
use as much memory as they want, but they can only use 50M kernel memory.
|
||||
|
||||
### Swappiness constraint
|
||||
|
||||
By default, a container's kernel can swap out a percentage of anonymous pages.
|
||||
|
||||
@@ -4,6 +4,7 @@ package registry
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -74,7 +75,7 @@ func loadTLSConfig(ctx context.Context, directory string, tlsConfig *tls.Config)
|
||||
switch filepath.Ext(f.Name()) {
|
||||
case ".crt":
|
||||
if tlsConfig.RootCAs == nil {
|
||||
systemPool, err := tlsconfig.SystemCertPool()
|
||||
systemPool, err := x509.SystemCertPool()
|
||||
if err != nil {
|
||||
return invalidParam(fmt.Errorf("unable to get system cert pool: %w", err))
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ docker-run - Create and run a new container from an image
|
||||
[**--ip6**[=*IPv6-ADDRESS*]]
|
||||
[**--ipc**[=*IPC*]]
|
||||
[**--isolation**[=*default*]]
|
||||
[**--kernel-memory**[=*KERNEL-MEMORY*]]
|
||||
[**-l**|**--label**[=*[]*]]
|
||||
[**--label-file**[=*[]*]]
|
||||
[**--link**[=*[]*]]
|
||||
@@ -410,15 +409,6 @@ is `hyperv`. Linux only supports `default`.
|
||||
**-l**, **--label** *key*=*value*
|
||||
Set metadata on the container (for example, **--label com.example.key=value**).
|
||||
|
||||
**--kernel-memory**=*number*[*S*]
|
||||
Kernel memory limit; *S* is an optional suffix which can be one of **b**, **k**, **m**, or **g**.
|
||||
|
||||
Constrains the kernel memory available to a container. If a limit of 0
|
||||
is specified (not using **--kernel-memory**), the container's kernel memory
|
||||
is not limited. If you specify a limit, it may be rounded up to a multiple
|
||||
of the operating system's page size and the value can be very large,
|
||||
millions of trillions.
|
||||
|
||||
**--label-file**=[]
|
||||
Read in a line delimited file of labels
|
||||
|
||||
|
||||
@@ -4,25 +4,11 @@ resources from their Docker host. With a single command, you can place
|
||||
limits on a single container or on many. To specify more than one container,
|
||||
provide space-separated list of container names or IDs.
|
||||
|
||||
With the exception of the **--kernel-memory** option, you can specify these
|
||||
options on a running or a stopped container. On kernel version older than
|
||||
4.6, You can only update **--kernel-memory** on a stopped container or on
|
||||
a running container with kernel memory initialized.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
## kernel-memory
|
||||
|
||||
Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)
|
||||
|
||||
Note that on kernel version older than 4.6, you can not update kernel memory on
|
||||
a running container if the container is started without kernel memory initialized,
|
||||
in this case, it can only be updated after it's stopped. The new setting takes
|
||||
effect when the container is started.
|
||||
|
||||
## memory
|
||||
|
||||
Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
|
||||
Memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)
|
||||
|
||||
Note that the memory should be smaller than the already set swap memory limit.
|
||||
If you want update a memory limit bigger than the already set swap memory limit,
|
||||
@@ -52,41 +38,6 @@ To update multiple resource configurations for multiple containers:
|
||||
$ docker container update --cpu-shares 512 -m 300M abebf7571666 hopeful_morse
|
||||
```
|
||||
|
||||
### Update a container's kernel memory constraints
|
||||
|
||||
You can update a container's kernel memory limit using the **--kernel-memory**
|
||||
option. On kernel version older than 4.6, this option can be updated on a
|
||||
running container only if the container was started with **--kernel-memory**.
|
||||
If the container was started *without* **--kernel-memory** you need to stop
|
||||
the container before updating kernel memory.
|
||||
|
||||
NOTE: The **--kernel-memory** option has been deprecated since Docker 20.10.
|
||||
|
||||
For example, if you started a container with this command:
|
||||
|
||||
```console
|
||||
$ docker run -dit --name test --kernel-memory 50M ubuntu bash
|
||||
```
|
||||
|
||||
You can update kernel memory while the container is running:
|
||||
|
||||
```console
|
||||
$ docker container update --kernel-memory 80M test
|
||||
```
|
||||
|
||||
If you started a container *without* kernel memory initialized:
|
||||
|
||||
```console
|
||||
$ docker run -dit --name test2 --memory 300M ubuntu bash
|
||||
```
|
||||
|
||||
Update kernel memory of running container `test2` will fail. You need to stop
|
||||
the container before updating the **--kernel-memory** setting. The next time you
|
||||
start it, the container uses the new value.
|
||||
|
||||
Kernel version newer than (include) 4.6 does not have this limitation, you
|
||||
can use `--kernel-memory` the same way as other options.
|
||||
|
||||
### Update a container's restart policy
|
||||
|
||||
You can change a container's restart policy on a running container. The new
|
||||
|
||||
@@ -318,8 +318,7 @@ func TestPortOptInvalidSimpleSyntax(t *testing.T) {
|
||||
},
|
||||
{
|
||||
value: "",
|
||||
expectedError: "invalid proto: ",
|
||||
// expectedError: "no port specified: <empty>", // FIXME(thaJeztah): re-enable once https://github.com/docker/go-connections/pull/143 is in a go-connections release.
|
||||
expectedError: "no port specified: <empty>",
|
||||
},
|
||||
{
|
||||
value: "1.1.1.1:80:80",
|
||||
|
||||
+23
-23
@@ -18,8 +18,8 @@ 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.5
|
||||
github.com/docker/go-connections v0.6.0
|
||||
github.com/docker/docker-credential-helpers v0.9.6
|
||||
github.com/docker/go-connections v0.7.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/fvbommel/sortorder v1.1.0
|
||||
github.com/go-jose/go-jose/v4 v4.1.4
|
||||
@@ -28,10 +28,10 @@ require (
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/mattn/go-runewidth v0.0.22
|
||||
github.com/mattn/go-runewidth v0.0.23
|
||||
github.com/moby/go-archive v0.2.0
|
||||
github.com/moby/moby/api v1.54.1
|
||||
github.com/moby/moby/client v0.4.0
|
||||
github.com/moby/moby/api v1.54.2
|
||||
github.com/moby/moby/client v0.4.1
|
||||
github.com/moby/patternmatcher v0.6.1
|
||||
github.com/moby/swarmkit/v2 v2.1.1
|
||||
github.com/moby/sys/atomicwriter v0.1.0
|
||||
@@ -49,19 +49,19 @@ require (
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/tonistiigi/go-rosetta v0.0.0-20220804170347-3f4430f2d346
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0
|
||||
go.opentelemetry.io/otel v1.42.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0
|
||||
go.opentelemetry.io/otel/metric v1.42.0
|
||||
go.opentelemetry.io/otel/sdk v1.42.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0
|
||||
go.opentelemetry.io/otel/trace v1.42.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0
|
||||
go.opentelemetry.io/otel v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0
|
||||
go.opentelemetry.io/otel/metric v1.43.0
|
||||
go.opentelemetry.io/otel/sdk v1.43.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0
|
||||
go.opentelemetry.io/otel/trace v1.43.0
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/sys v0.42.0
|
||||
golang.org/x/term v0.41.0
|
||||
golang.org/x/text v0.35.0
|
||||
golang.org/x/sys v0.43.0
|
||||
golang.org/x/term v0.42.0
|
||||
golang.org/x/text v0.36.0
|
||||
gotest.tools/v3 v3.5.2
|
||||
tags.cncf.io/container-device-interface v1.1.0
|
||||
)
|
||||
@@ -98,13 +98,13 @@ require (
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
go.etcd.io/etcd/raft/v3 v3.5.16 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
golang.org/x/mod v0.34.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
golang.org/x/mod v0.35.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/grpc v1.80.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
||||
+48
-48
@@ -40,10 +40,10 @@ 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.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
|
||||
github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||
github.com/docker/docker-credential-helpers v0.9.6 h1:cT2PbRPSlnMmNTfT2TDMXRyQ1KMWHG7xoTLBcn1ZNv0=
|
||||
github.com/docker/docker-credential-helpers v0.9.6/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
|
||||
github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
|
||||
github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q=
|
||||
github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4=
|
||||
github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
@@ -106,17 +106,17 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mattn/go-runewidth v0.0.22 h1:76lXsPn6FyHtTY+jt2fTTvsMUCZq1k0qwRsAMuxzKAk=
|
||||
github.com/mattn/go-runewidth v0.0.22/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
|
||||
github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
|
||||
github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4=
|
||||
github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
|
||||
github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw=
|
||||
github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g=
|
||||
github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg=
|
||||
github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
|
||||
github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY=
|
||||
github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ=
|
||||
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.1 h1:yvTJ8MMCc3f0qTA44J6R59EZ5yZawdYopkpuLk4+ICU=
|
||||
@@ -206,26 +206,26 @@ go.etcd.io/etcd/raft/v3 v3.5.16 h1:zBXA3ZUpYs1AwiLGPafYAKKl/CORn/uaxYDwlNwndAk=
|
||||
go.etcd.io/etcd/raft/v3 v3.5.16/go.mod h1:P4UP14AxofMJ/54boWilabqqWoW9eLodl6I5GdGzazI=
|
||||
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.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
|
||||
go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho=
|
||||
go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0 h1:zWWrB1U6nqhS/k6zYB74CjRpuiitRtLLi68VcgmOEto=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0/go.mod h1:2qXPNBX1OVRC0IwOnfo1ljoid+RD0QK3443EaqVlsOU=
|
||||
go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4=
|
||||
go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI=
|
||||
go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo=
|
||||
go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc=
|
||||
go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY=
|
||||
go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0 h1:8UQVDcZxOJLtX6gxtDt3vY2WTgvZqMQRzjsqiIHQdkc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.43.0/go.mod h1:2lmweYCiHYpEjQ/lSJBYhj9jP1zvCvQW4BqL9dnT7FQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
@@ -236,16 +236,16 @@ 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.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -261,14 +261,14 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
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.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -279,14 +279,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
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-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
|
||||
+36
-36
@@ -27,19 +27,15 @@ type PortSet map[Port]struct{}
|
||||
type Port string
|
||||
|
||||
// NewPort creates a new instance of a Port given a protocol and port number or port range
|
||||
func NewPort(proto, port string) (Port, error) {
|
||||
// Check for parsing issues on "port" now so we can avoid having
|
||||
// to check it later on.
|
||||
|
||||
portStartInt, portEndInt, err := ParsePortRangeToInt(port)
|
||||
func NewPort(proto, portOrRange string) (Port, error) {
|
||||
start, end, err := parsePortRange(portOrRange)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if portStartInt == portEndInt {
|
||||
return Port(fmt.Sprintf("%d/%s", portStartInt, proto)), nil
|
||||
if start == end {
|
||||
return Port(fmt.Sprintf("%d/%s", start, proto)), nil
|
||||
}
|
||||
return Port(fmt.Sprintf("%d-%d/%s", portStartInt, portEndInt, proto)), nil
|
||||
return Port(fmt.Sprintf("%d-%d/%s", start, end, proto)), nil
|
||||
}
|
||||
|
||||
// ParsePort parses the port number string and returns an int
|
||||
@@ -47,49 +43,53 @@ func ParsePort(rawPort string) (int, error) {
|
||||
if rawPort == "" {
|
||||
return 0, nil
|
||||
}
|
||||
port, err := strconv.ParseUint(rawPort, 10, 16)
|
||||
port, err := parsePortNumber(rawPort)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid port '%s': %w", rawPort, errors.Unwrap(err))
|
||||
return 0, fmt.Errorf("invalid port '%s': %w", rawPort, err)
|
||||
}
|
||||
return int(port), nil
|
||||
return port, nil
|
||||
}
|
||||
|
||||
// ParsePortRangeToInt parses the port range string and returns start/end ints
|
||||
func ParsePortRangeToInt(rawPort string) (int, int, error) {
|
||||
func ParsePortRangeToInt(rawPort string) (startPort, endPort int, _ error) {
|
||||
if rawPort == "" {
|
||||
// TODO(thaJeztah): consider making this an error; this was kept to keep existing behavior.
|
||||
return 0, 0, nil
|
||||
}
|
||||
start, end, err := ParsePortRange(rawPort)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(start), int(end), nil
|
||||
return parsePortRange(rawPort)
|
||||
}
|
||||
|
||||
// Proto returns the protocol of a Port
|
||||
func (p Port) Proto() string {
|
||||
proto, _ := SplitProtoPort(string(p))
|
||||
_, proto, _ := strings.Cut(string(p), "/")
|
||||
if proto == "" {
|
||||
proto = "tcp"
|
||||
}
|
||||
return proto
|
||||
}
|
||||
|
||||
// Port returns the port number of a Port
|
||||
func (p Port) Port() string {
|
||||
_, port := SplitProtoPort(string(p))
|
||||
port, _, _ := strings.Cut(string(p), "/")
|
||||
return port
|
||||
}
|
||||
|
||||
// Int returns the port number of a Port as an int
|
||||
// Int returns the port number of a Port as an int. It assumes [Port]
|
||||
// is valid, and returns 0 otherwise.
|
||||
func (p Port) Int() int {
|
||||
portStr := p.Port()
|
||||
// We don't need to check for an error because we're going to
|
||||
// assume that any error would have been found, and reported, in NewPort()
|
||||
port, _ := ParsePort(portStr)
|
||||
// assume that any error would have been found, and reported, in [NewPort]
|
||||
port, _ := parsePortNumber(p.Port())
|
||||
return port
|
||||
}
|
||||
|
||||
// Range returns the start/end port numbers of a Port range as ints
|
||||
func (p Port) Range() (int, int, error) {
|
||||
return ParsePortRangeToInt(p.Port())
|
||||
portRange := p.Port()
|
||||
if portRange == "" {
|
||||
return 0, 0, nil
|
||||
}
|
||||
return parsePortRange(portRange)
|
||||
}
|
||||
|
||||
// SplitProtoPort splits a port(range) and protocol, formatted as "<portnum>/[<proto>]"
|
||||
@@ -173,6 +173,10 @@ func splitParts(rawport string) (hostIP, hostPort, containerPort string) {
|
||||
func ParsePortSpec(rawPort string) ([]PortMapping, error) {
|
||||
ip, hostPort, containerPort := splitParts(rawPort)
|
||||
proto, containerPort := SplitProtoPort(containerPort)
|
||||
if containerPort == "" {
|
||||
return nil, fmt.Errorf("no port specified: %s<empty>", rawPort)
|
||||
}
|
||||
|
||||
proto = strings.ToLower(proto)
|
||||
if err := validateProto(proto); err != nil {
|
||||
return nil, err
|
||||
@@ -189,18 +193,15 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
|
||||
if ip != "" && net.ParseIP(ip) == nil {
|
||||
return nil, errors.New("invalid IP address: " + ip)
|
||||
}
|
||||
if containerPort == "" {
|
||||
return nil, fmt.Errorf("no port specified: %s<empty>", rawPort)
|
||||
}
|
||||
|
||||
startPort, endPort, err := ParsePortRange(containerPort)
|
||||
startPort, endPort, err := parsePortRange(containerPort)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid containerPort: " + containerPort)
|
||||
}
|
||||
|
||||
var startHostPort, endHostPort uint64
|
||||
var startHostPort, endHostPort int
|
||||
if hostPort != "" {
|
||||
startHostPort, endHostPort, err = ParsePortRange(hostPort)
|
||||
startHostPort, endHostPort, err = parsePortRange(hostPort)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid hostPort: " + hostPort)
|
||||
}
|
||||
@@ -217,19 +218,18 @@ func ParsePortSpec(rawPort string) ([]PortMapping, error) {
|
||||
count := endPort - startPort + 1
|
||||
ports := make([]PortMapping, 0, count)
|
||||
|
||||
for i := uint64(0); i < count; i++ {
|
||||
cPort := Port(strconv.FormatUint(startPort+i, 10) + "/" + proto)
|
||||
for i := range count {
|
||||
hPort := ""
|
||||
if hostPort != "" {
|
||||
hPort = strconv.FormatUint(startHostPort+i, 10)
|
||||
hPort = strconv.Itoa(startHostPort + i)
|
||||
// Set hostPort to a range only if there is a single container port
|
||||
// and a dynamic host port.
|
||||
if count == 1 && startHostPort != endHostPort {
|
||||
hPort += "-" + strconv.FormatUint(endHostPort, 10)
|
||||
hPort += "-" + strconv.Itoa(endHostPort)
|
||||
}
|
||||
}
|
||||
ports = append(ports, PortMapping{
|
||||
Port: cPort,
|
||||
Port: Port(strconv.Itoa(startPort+i) + "/" + proto),
|
||||
Binding: PortBinding{HostIP: ip, HostPort: hPort},
|
||||
})
|
||||
}
|
||||
|
||||
+42
-15
@@ -2,32 +2,59 @@ package nat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParsePortRange parses and validates the specified string as a port-range (8000-9000)
|
||||
func ParsePortRange(ports string) (uint64, uint64, error) {
|
||||
// ParsePortRange parses and validates the specified string as a port range (e.g., "8000-9000").
|
||||
func ParsePortRange(ports string) (startPort, endPort uint64, _ error) {
|
||||
start, end, err := parsePortRange(ports)
|
||||
return uint64(start), uint64(end), err
|
||||
}
|
||||
|
||||
// parsePortRange parses and validates the specified string as a port range (e.g., "8000-9000").
|
||||
func parsePortRange(ports string) (startPort, endPort int, _ error) {
|
||||
if ports == "" {
|
||||
return 0, 0, errors.New("empty string specified for ports")
|
||||
}
|
||||
if !strings.Contains(ports, "-") {
|
||||
start, err := strconv.ParseUint(ports, 10, 16)
|
||||
end := start
|
||||
return start, end, err
|
||||
start, end, ok := strings.Cut(ports, "-")
|
||||
|
||||
startPort, err := parsePortNumber(start)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("invalid start port '%s': %w", start, err)
|
||||
}
|
||||
if !ok || start == end {
|
||||
return startPort, startPort, nil
|
||||
}
|
||||
|
||||
parts := strings.Split(ports, "-")
|
||||
start, err := strconv.ParseUint(parts[0], 10, 16)
|
||||
endPort, err = parsePortNumber(end)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
return 0, 0, fmt.Errorf("invalid end port '%s': %w", end, err)
|
||||
}
|
||||
end, err := strconv.ParseUint(parts[1], 10, 16)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
if endPort < startPort {
|
||||
return 0, 0, errors.New("invalid port range: " + ports)
|
||||
}
|
||||
if end < start {
|
||||
return 0, 0, errors.New("invalid range specified for port: " + ports)
|
||||
return startPort, endPort, nil
|
||||
}
|
||||
|
||||
// parsePortNumber parses rawPort into an int, unwrapping strconv errors
|
||||
// and returning a single "out of range" error for any value outside 0–65535.
|
||||
func parsePortNumber(rawPort string) (int, error) {
|
||||
if rawPort == "" {
|
||||
return 0, errors.New("value is empty")
|
||||
}
|
||||
return start, end, nil
|
||||
port, err := strconv.ParseInt(rawPort, 10, 0)
|
||||
if err != nil {
|
||||
var numErr *strconv.NumError
|
||||
if errors.As(err, &numErr) {
|
||||
err = numErr.Err
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
if port < 0 || port > 65535 {
|
||||
return 0, errors.New("value out of range (0–65535)")
|
||||
}
|
||||
|
||||
return int(port), nil
|
||||
}
|
||||
|
||||
+27
-15
@@ -34,8 +34,10 @@ func Sort(ports []Port, predicate func(i, j Port) bool) {
|
||||
}
|
||||
|
||||
type portMapEntry struct {
|
||||
port Port
|
||||
binding PortBinding
|
||||
port Port
|
||||
binding *PortBinding
|
||||
portInt int
|
||||
portProto string
|
||||
}
|
||||
|
||||
type portMapSorter []portMapEntry
|
||||
@@ -48,23 +50,36 @@ func (s portMapSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
// 2. larger port
|
||||
// 3. port with tcp protocol
|
||||
func (s portMapSorter) Less(i, j int) bool {
|
||||
pi, pj := s[i].port, s[j].port
|
||||
hpi, hpj := toInt(s[i].binding.HostPort), toInt(s[j].binding.HostPort)
|
||||
return hpi > hpj || pi.Int() > pj.Int() || (pi.Int() == pj.Int() && strings.ToLower(pi.Proto()) == "tcp")
|
||||
pi, pj := s[i].portInt, s[j].portInt
|
||||
var hpi, hpj int
|
||||
if s[i].binding != nil {
|
||||
hpi = toInt(s[i].binding.HostPort)
|
||||
}
|
||||
if s[j].binding != nil {
|
||||
hpj = toInt(s[j].binding.HostPort)
|
||||
}
|
||||
return hpi > hpj || pi > pj || (pi == pj && strings.EqualFold(s[i].portProto, "tcp"))
|
||||
}
|
||||
|
||||
// SortPortMap sorts the list of ports and their respected mapping. The ports
|
||||
// will explicit HostPort will be placed first.
|
||||
func SortPortMap(ports []Port, bindings PortMap) {
|
||||
func SortPortMap(ports []Port, bindings map[Port][]PortBinding) {
|
||||
s := portMapSorter{}
|
||||
for _, p := range ports {
|
||||
portInt, portProto := p.Int(), p.Proto()
|
||||
if binding, ok := bindings[p]; ok && len(binding) > 0 {
|
||||
for _, b := range binding {
|
||||
s = append(s, portMapEntry{port: p, binding: b})
|
||||
s = append(s, portMapEntry{
|
||||
port: p, binding: &b,
|
||||
portInt: portInt, portProto: portProto,
|
||||
})
|
||||
}
|
||||
bindings[p] = []PortBinding{}
|
||||
} else {
|
||||
s = append(s, portMapEntry{port: p})
|
||||
s = append(s, portMapEntry{
|
||||
port: p,
|
||||
portInt: portInt, portProto: portProto,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,16 +96,13 @@ func SortPortMap(ports []Port, bindings PortMap) {
|
||||
i++
|
||||
}
|
||||
// reorder bindings for this port
|
||||
if _, ok := bindings[entry.port]; ok {
|
||||
bindings[entry.port] = append(bindings[entry.port], entry.binding)
|
||||
if entry.binding != nil {
|
||||
bindings[entry.port] = append(bindings[entry.port], *entry.binding)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toInt(s string) uint64 {
|
||||
i, _, err := ParsePortRange(s)
|
||||
if err != nil {
|
||||
i = 0
|
||||
}
|
||||
func toInt(s string) int {
|
||||
i, _, _ := parsePortRange(s)
|
||||
return i
|
||||
}
|
||||
|
||||
+30
-30
@@ -1,48 +1,57 @@
|
||||
package sockets
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var errClosed = errors.New("use of closed network connection")
|
||||
|
||||
// InmemSocket implements net.Listener using in-memory only connections.
|
||||
type InmemSocket struct {
|
||||
chConn chan net.Conn
|
||||
chClose chan struct{}
|
||||
addr string
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// dummyAddr is used to satisfy net.Addr for the in-mem socket
|
||||
// it is just stored as a string and returns the string for all calls
|
||||
type dummyAddr string
|
||||
|
||||
// NewInmemSocket creates an in-memory only net.Listener
|
||||
// The addr argument can be any string, but is used to satisfy the `Addr()` part
|
||||
// of the net.Listener interface
|
||||
// Network returns the addr string, satisfies net.Addr
|
||||
func (a dummyAddr) Network() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// String returns the string form
|
||||
func (a dummyAddr) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// InmemSocket implements [net.Listener] using in-memory only connections.
|
||||
type InmemSocket struct {
|
||||
chConn chan net.Conn
|
||||
chClose chan struct{}
|
||||
addr dummyAddr
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewInmemSocket creates an in-memory only [net.Listener]. The addr argument
|
||||
// can be any string, but is used to satisfy the [net.Listener.Addr] part
|
||||
// of the [net.Listener] interface
|
||||
func NewInmemSocket(addr string, bufSize int) *InmemSocket {
|
||||
return &InmemSocket{
|
||||
chConn: make(chan net.Conn, bufSize),
|
||||
chClose: make(chan struct{}),
|
||||
addr: addr,
|
||||
addr: dummyAddr(addr),
|
||||
}
|
||||
}
|
||||
|
||||
// Addr returns the socket's addr string to satisfy net.Listener
|
||||
func (s *InmemSocket) Addr() net.Addr {
|
||||
return dummyAddr(s.addr)
|
||||
return s.addr
|
||||
}
|
||||
|
||||
// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
|
||||
// Accept implements the Accept method in the Listener interface; it waits
|
||||
// for the next call and returns a generic Conn. It returns a [net.ErrClosed]
|
||||
// if the connection is already closed.
|
||||
func (s *InmemSocket) Accept() (net.Conn, error) {
|
||||
select {
|
||||
case conn := <-s.chConn:
|
||||
return conn, nil
|
||||
case <-s.chClose:
|
||||
return nil, errClosed
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,24 +67,15 @@ func (s *InmemSocket) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Dial is used to establish a connection with the in-mem server
|
||||
// Dial is used to establish a connection with the in-mem server.
|
||||
// It returns a [net.ErrClosed] if the connection is already closed.
|
||||
func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) {
|
||||
srvConn, clientConn := net.Pipe()
|
||||
select {
|
||||
case s.chConn <- srvConn:
|
||||
case <-s.chClose:
|
||||
return nil, errClosed
|
||||
return nil, net.ErrClosed
|
||||
}
|
||||
|
||||
return clientConn, nil
|
||||
}
|
||||
|
||||
// Network returns the addr string, satisfies net.Addr
|
||||
func (a dummyAddr) Network() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// String returns the string form
|
||||
func (a dummyAddr) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package sockets
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetProxyEnv allows access to the uppercase and the lowercase forms of
|
||||
// proxy-related variables. See the Go specification for details on these
|
||||
// variables. https://golang.org/pkg/net/http/
|
||||
//
|
||||
// Deprecated: this function was used as helper for [DialerFromEnvironment] and is no longer used. It will be removed in the next release.
|
||||
func GetProxyEnv(key string) string {
|
||||
proxyValue := os.Getenv(strings.ToUpper(key))
|
||||
if proxyValue == "" {
|
||||
return os.Getenv(strings.ToLower(key))
|
||||
}
|
||||
return proxyValue
|
||||
}
|
||||
|
||||
// DialerFromEnvironment was previously used to configure a net.Dialer to route
|
||||
// connections through a SOCKS proxy.
|
||||
//
|
||||
// Deprecated: SOCKS proxies are now supported by configuring only
|
||||
// http.Transport.Proxy, and no longer require changing http.Transport.Dial.
|
||||
// Therefore, only [sockets.ConfigureTransport] needs to be called, and any
|
||||
// [sockets.DialerFromEnvironment] calls can be dropped.
|
||||
func DialerFromEnvironment(direct *net.Dialer) (*net.Dialer, error) {
|
||||
return direct, nil
|
||||
}
|
||||
+12
-12
@@ -27,11 +27,19 @@ var ErrProtocolNotAvailable = errors.New("protocol not available")
|
||||
// make sure you do it _after_ any subsequent calls to ConfigureTransport is made against the same
|
||||
// [http.Transport].
|
||||
func ConfigureTransport(tr *http.Transport, proto, addr string) error {
|
||||
if tr.MaxIdleConns == 0 {
|
||||
// prevent long-lived processes from leaking connections
|
||||
// due to idle connections not being released.
|
||||
//
|
||||
// TODO: see if we can also address this from the server side; see: https://github.com/moby/moby/issues/45539
|
||||
tr.MaxIdleConns = 6
|
||||
tr.IdleConnTimeout = 30 * time.Second
|
||||
}
|
||||
switch proto {
|
||||
case "unix":
|
||||
return configureUnixTransport(tr, proto, addr)
|
||||
return configureUnixTransport(tr, addr)
|
||||
case "npipe":
|
||||
return configureNpipeTransport(tr, proto, addr)
|
||||
return configureNpipeTransport(tr, addr)
|
||||
default:
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
tr.DisableCompression = false
|
||||
@@ -42,15 +50,7 @@ func ConfigureTransport(tr *http.Transport, proto, addr string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DialPipe connects to a Windows named pipe. It is not supported on
|
||||
// non-Windows platforms.
|
||||
//
|
||||
// Deprecated: use [github.com/Microsoft/go-winio.DialPipe] or [github.com/Microsoft/go-winio.DialPipeContext].
|
||||
func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return dialPipe(addr, timeout)
|
||||
}
|
||||
|
||||
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||||
func configureUnixTransport(tr *http.Transport, addr string) error {
|
||||
if len(addr) > maxUnixSocketPathSize {
|
||||
return fmt.Errorf("unix socket path %q is too long", addr)
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||||
Timeout: defaultTimeout,
|
||||
}
|
||||
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, proto, addr)
|
||||
return dialer.DialContext(ctx, "unix", addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+1
-12
@@ -2,17 +2,6 @@
|
||||
|
||||
package sockets
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
|
||||
func configureNpipeTransport(any, string) error {
|
||||
return ErrProtocolNotAvailable
|
||||
}
|
||||
|
||||
func dialPipe(_ string, _ time.Duration) (net.Conn, error) {
|
||||
return nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
|
||||
+1
-6
@@ -4,12 +4,11 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
|
||||
func configureNpipeTransport(tr *http.Transport, addr string) error {
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
@@ -17,7 +16,3 @@ func configureNpipeTransport(tr *http.Transport, proto, addr string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dialPipe(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return winio.DialPipe(addr, &timeout)
|
||||
}
|
||||
|
||||
+123
-1
@@ -1,6 +1,128 @@
|
||||
package sockets
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// BasePermissions defines the default DACL, which allows Administrators
|
||||
// and LocalSystem full access (similar to defaults used in [moby]);
|
||||
//
|
||||
// - D:P: DACL without inheritance (protected, (P)).
|
||||
// - (A;;GA;;;BA): Allow full access (GA) for built-in Administrators (BA).
|
||||
// - (A;;GA;;;SY); Allow full access (GA) for LocalSystem (SY).
|
||||
// - Any other user is denied access.
|
||||
//
|
||||
// [moby]: https://github.com/moby/moby/blob/6b45c76a233b1b8b56465f76c21c09fd7920e82d/daemon/listeners/listeners_windows.go#L53-L59
|
||||
const BasePermissions = "D:P(A;;GA;;;BA)(A;;GA;;;SY)"
|
||||
|
||||
// WithBasePermissions sets a default DACL, which allows Administrators
|
||||
// and LocalSystem full access (similar to defaults used in [moby]);
|
||||
//
|
||||
// - D:P: DACL without inheritance (protected, (P)).
|
||||
// - (A;;GA;;;BA): Allow full access (GA) for built-in Administrators (BA).
|
||||
// - (A;;GA;;;SY); Allow full access (GA) for LocalSystem (SY).
|
||||
// - Any other user is denied access.
|
||||
//
|
||||
// [moby]: https://github.com/moby/moby/blob/6b45c76a233b1b8b56465f76c21c09fd7920e82d/daemon/listeners/listeners_windows.go#L53-L59
|
||||
func WithBasePermissions() SockOption {
|
||||
return withSDDL(BasePermissions)
|
||||
}
|
||||
|
||||
// WithAdditionalUsersAndGroups modifies the socket file's DACL to grant
|
||||
// access to additional users and groups.
|
||||
//
|
||||
// It sets [BasePermissions] on the socket path and grants the given additional
|
||||
// users and groups to generic read (GR) and write (GW) access. It returns
|
||||
// an error if no groups were given, when failing to resolve any of the
|
||||
// additional users and groups, or when failing to apply the ACL.
|
||||
func WithAdditionalUsersAndGroups(additionalUsersAndGroups []string) SockOption {
|
||||
return func(path string) error {
|
||||
if len(additionalUsersAndGroups) == 0 {
|
||||
return errors.New("no additional users specified")
|
||||
}
|
||||
sd, err := getSecurityDescriptor(additionalUsersAndGroups...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("looking up SID: %w", err)
|
||||
}
|
||||
return withSDDL(sd)(path)
|
||||
}
|
||||
}
|
||||
|
||||
// withSDDL applies the given SDDL to the socket. It returns an error
|
||||
// when failing parse the SDDL, or if the DACL was defaulted.
|
||||
//
|
||||
// TODO(thaJeztah); this is not exported yet, as some of the checks may need review if they're not too opinionated.
|
||||
func withSDDL(sddl string) SockOption {
|
||||
return func(path string) error {
|
||||
sd, err := windows.SecurityDescriptorFromString(sddl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing SDDL: %w", err)
|
||||
}
|
||||
dacl, defaulted, err := sd.DACL()
|
||||
if err != nil {
|
||||
return fmt.Errorf("extracting DACL: %w", err)
|
||||
}
|
||||
if dacl == nil || defaulted {
|
||||
// should never be hit with our [DefaultPermissions],
|
||||
// as it contains "D:" and "P" (protected, don't inherit).
|
||||
return errors.New("no DACL found in security descriptor or defaulted")
|
||||
}
|
||||
return windows.SetNamedSecurityInfo(
|
||||
path,
|
||||
windows.SE_FILE_OBJECT,
|
||||
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
|
||||
nil, // do not change the owner
|
||||
nil, // do not change the owner
|
||||
dacl,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// NewUnixSocket creates a new unix socket.
|
||||
//
|
||||
// It sets [BasePermissions] on the socket path and grants the given additional
|
||||
// users and groups to generic read (GR) and write (GW) access. It returns
|
||||
// an error when failing to resolve any of the additional users and groups,
|
||||
// or when failing to apply the ACL.
|
||||
func NewUnixSocket(path string, additionalUsersAndGroups []string) (net.Listener, error) {
|
||||
var opts []SockOption
|
||||
if len(additionalUsersAndGroups) > 0 {
|
||||
opts = append(opts, WithAdditionalUsersAndGroups(additionalUsersAndGroups))
|
||||
} else {
|
||||
opts = append(opts, WithBasePermissions())
|
||||
}
|
||||
return NewUnixSocketWithOpts(path, opts...)
|
||||
}
|
||||
|
||||
// getSecurityDescriptor returns the DACL for the Unix socket.
|
||||
//
|
||||
// By default, it grants [BasePermissions], but allows for additional
|
||||
// users and groups to get generic read (GR) and write (GW) access. It
|
||||
// returns an error when failing to resolve any of the additional users
|
||||
// and groups.
|
||||
func getSecurityDescriptor(additionalUsersAndGroups ...string) (string, error) {
|
||||
sddl := BasePermissions
|
||||
|
||||
// Grant generic read (GR) and write (GW) access to whatever
|
||||
// additional users or groups were specified.
|
||||
//
|
||||
// TODO(thaJeztah): should we fail on, or remove duplicates?
|
||||
for _, g := range additionalUsersAndGroups {
|
||||
sid, err := winio.LookupSidByName(strings.TrimSpace(g))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("looking up SID: %w", err)
|
||||
}
|
||||
sddl += fmt.Sprintf("(A;;GRGW;;;%s)", sid)
|
||||
}
|
||||
return sddl, nil
|
||||
}
|
||||
|
||||
func listenUnix(path string) (net.Listener, error) {
|
||||
return net.Listen("unix", path)
|
||||
|
||||
+7
-11
@@ -1,16 +1,12 @@
|
||||
package tlsconfig
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"runtime"
|
||||
)
|
||||
import "crypto/x509"
|
||||
|
||||
// SystemCertPool returns a copy of the system cert pool,
|
||||
// returns an error if failed to load or empty pool on windows.
|
||||
// SystemCertPool returns a copy of the system cert pool.
|
||||
//
|
||||
// Deprecated: use [x509.SystemCertPool] instead.
|
||||
//
|
||||
//go:fix inline
|
||||
func SystemCertPool() (*x509.CertPool, error) {
|
||||
certpool, err := x509.SystemCertPool()
|
||||
if err != nil && runtime.GOOS == "windows" {
|
||||
return x509.NewCertPool(), nil
|
||||
}
|
||||
return certpool, err
|
||||
return x509.SystemCertPool()
|
||||
}
|
||||
|
||||
+20
-8
@@ -34,6 +34,9 @@ type Options struct {
|
||||
// the system pool will be used.
|
||||
ExclusiveRootPools bool
|
||||
MinVersion uint16
|
||||
|
||||
// systemCertPool allows mocking the system cert-pool for testing.
|
||||
systemCertPool func() (*x509.CertPool, error)
|
||||
}
|
||||
|
||||
// DefaultServerAcceptedCiphers should be uses by code which already has a crypto/tls
|
||||
@@ -47,6 +50,8 @@ var defaultCipherSuites = []uint16{
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
}
|
||||
|
||||
// ServerDefault returns a secure-enough TLS configuration for the server TLS configuration.
|
||||
@@ -75,26 +80,33 @@ func defaultConfig(ops ...func(*tls.Config)) *tls.Config {
|
||||
}
|
||||
|
||||
// certPool returns an X.509 certificate pool from `caFile`, the certificate file.
|
||||
func certPool(caFile string, exclusivePool bool) (*x509.CertPool, error) {
|
||||
func certPool(opts Options) (*x509.CertPool, error) {
|
||||
// If we should verify the server, we need to load a trusted ca
|
||||
var (
|
||||
pool *x509.CertPool
|
||||
err error
|
||||
)
|
||||
if exclusivePool {
|
||||
if opts.ExclusiveRootPools {
|
||||
pool = x509.NewCertPool()
|
||||
} else {
|
||||
pool, err = SystemCertPool()
|
||||
if opts.systemCertPool != nil {
|
||||
pool, err = opts.systemCertPool()
|
||||
} else {
|
||||
pool, err = x509.SystemCertPool()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read system certificates: %v", err)
|
||||
}
|
||||
}
|
||||
pemData, err := os.ReadFile(caFile)
|
||||
if opts.CAFile == "" {
|
||||
return pool, nil
|
||||
}
|
||||
pemData, err := os.ReadFile(opts.CAFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read CA certificate %q: %v", caFile, err)
|
||||
return nil, fmt.Errorf("could not read CA certificate %q: %v", opts.CAFile, err)
|
||||
}
|
||||
if !pool.AppendCertsFromPEM(pemData) {
|
||||
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", caFile)
|
||||
return nil, fmt.Errorf("failed to append certificates from PEM file: %q", opts.CAFile)
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
@@ -197,7 +209,7 @@ func Client(options Options) (*tls.Config, error) {
|
||||
tlsConfig := defaultConfig()
|
||||
tlsConfig.InsecureSkipVerify = options.InsecureSkipVerify
|
||||
if !options.InsecureSkipVerify && options.CAFile != "" {
|
||||
CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
|
||||
CAs, err := certPool(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -230,7 +242,7 @@ func Server(options Options) (*tls.Config, error) {
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
||||
if options.ClientAuth >= tls.VerifyClientCertIfGiven && options.CAFile != "" {
|
||||
CAs, err := certPool(options.CAFile, options.ExclusiveRootPools)
|
||||
CAs, err := certPool(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+69
-22
@@ -24,10 +24,48 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
zerowidth table // combining + nonprint merged for faster zero-width lookup
|
||||
widewidth table // ambiguous + doublewidth merged for EA path
|
||||
)
|
||||
|
||||
func init() {
|
||||
zerowidth = mergeIntervals(combining, nonprint)
|
||||
widewidth = mergeIntervals(ambiguous, doublewidth)
|
||||
handleEnv()
|
||||
}
|
||||
|
||||
func mergeIntervals(t1, t2 table) table {
|
||||
merged := make(table, 0, len(t1)+len(t2))
|
||||
i, j := 0, 0
|
||||
for i < len(t1) && j < len(t2) {
|
||||
if t1[i].first <= t2[j].first {
|
||||
merged = append(merged, t1[i])
|
||||
i++
|
||||
} else {
|
||||
merged = append(merged, t2[j])
|
||||
j++
|
||||
}
|
||||
}
|
||||
merged = append(merged, t1[i:]...)
|
||||
merged = append(merged, t2[j:]...)
|
||||
if len(merged) == 0 {
|
||||
return merged
|
||||
}
|
||||
result := merged[:1]
|
||||
for _, iv := range merged[1:] {
|
||||
last := &result[len(result)-1]
|
||||
if iv.first <= last.last+1 {
|
||||
if iv.last > last.last {
|
||||
last.last = iv.last
|
||||
}
|
||||
} else {
|
||||
result = append(result, iv)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func handleEnv() {
|
||||
env := os.Getenv("RUNEWIDTH_EASTASIAN")
|
||||
if env == "" {
|
||||
@@ -52,15 +90,6 @@ type interval struct {
|
||||
|
||||
type table []interval
|
||||
|
||||
func inTables(r rune, ts ...table) bool {
|
||||
for _, t := range ts {
|
||||
if inTable(r, t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func inTable(r rune, t table) bool {
|
||||
if r < t[0].first {
|
||||
return false
|
||||
@@ -131,9 +160,7 @@ func (c *Condition) RuneWidth(r rune) int {
|
||||
return 0
|
||||
case r < 0x300:
|
||||
return 1
|
||||
case inTable(r, narrow):
|
||||
return 1
|
||||
case inTables(r, nonprint, combining):
|
||||
case inTable(r, zerowidth):
|
||||
return 0
|
||||
case inTable(r, doublewidth):
|
||||
return 2
|
||||
@@ -142,13 +169,13 @@ func (c *Condition) RuneWidth(r rune) int {
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case inTables(r, nonprint, combining):
|
||||
case inTable(r, zerowidth):
|
||||
return 0
|
||||
case inTable(r, narrow):
|
||||
return 1
|
||||
case inTables(r, ambiguous, doublewidth):
|
||||
case inTable(r, widewidth):
|
||||
return 2
|
||||
case !c.StrictEmojiNeutral && inTables(r, ambiguous, emoji, narrow):
|
||||
case !c.StrictEmojiNeutral && inTable(r, emoji):
|
||||
return 2
|
||||
default:
|
||||
return 1
|
||||
@@ -185,6 +212,16 @@ func (c *Condition) StringWidth(s string) (width int) {
|
||||
return c.RuneWidth(r)
|
||||
}
|
||||
}
|
||||
// ASCII fast path: no grapheme clustering needed for pure ASCII
|
||||
if isAllASCII(s) {
|
||||
for i := 0; i < len(s); i++ {
|
||||
b := s[i]
|
||||
if b >= 0x20 && b != 0x7F {
|
||||
width++
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
g := graphemes.FromString(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
@@ -199,6 +236,15 @@ func (c *Condition) StringWidth(s string) (width int) {
|
||||
return
|
||||
}
|
||||
|
||||
func isAllASCII(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= 0x80 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Truncate return string truncated with w cells
|
||||
func (c *Condition) Truncate(s string, w int, tail string) string {
|
||||
if c.StringWidth(s) <= w {
|
||||
@@ -264,24 +310,25 @@ func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
|
||||
// Wrap return string wrapped with w cells
|
||||
func (c *Condition) Wrap(s string, w int) string {
|
||||
width := 0
|
||||
out := ""
|
||||
var out strings.Builder
|
||||
out.Grow(len(s) + len(s)/w + 1)
|
||||
for _, r := range s {
|
||||
cw := c.RuneWidth(r)
|
||||
if r == '\n' {
|
||||
out += string(r)
|
||||
out.WriteRune(r)
|
||||
width = 0
|
||||
continue
|
||||
} else if width+cw > w {
|
||||
out += "\n"
|
||||
out.WriteByte('\n')
|
||||
width = 0
|
||||
out += string(r)
|
||||
out.WriteRune(r)
|
||||
width += cw
|
||||
continue
|
||||
}
|
||||
out += string(r)
|
||||
out.WriteRune(r)
|
||||
width += cw
|
||||
}
|
||||
return out
|
||||
return out.String()
|
||||
}
|
||||
|
||||
// FillLeft return string filled in left by spaces in w cells
|
||||
@@ -320,7 +367,7 @@ func RuneWidth(r rune) int {
|
||||
|
||||
// IsAmbiguousWidth returns whether is ambiguous width or not.
|
||||
func IsAmbiguousWidth(r rune) bool {
|
||||
return inTables(r, private, ambiguous)
|
||||
return inTable(r, private) || inTable(r, ambiguous)
|
||||
}
|
||||
|
||||
// IsCombiningWidth returns whether is combining width or not.
|
||||
|
||||
+28
-16
@@ -12,8 +12,9 @@ const rs = 0x1E
|
||||
|
||||
type DecoderFn func(v any) error
|
||||
|
||||
// NewJSONStreamDecoder builds adequate DecoderFn to read json records formatted with specified content-type
|
||||
func NewJSONStreamDecoder(r io.Reader, contentType string) DecoderFn {
|
||||
// NewJSONStreamDecoder builds a DecoderFn to read a stream of JSON records
|
||||
// formatted with the specified content-type.
|
||||
func NewJSONStreamDecoder(r io.Reader, contentType types.MediaType) DecoderFn {
|
||||
switch contentType {
|
||||
case types.MediaTypeJSONSequence:
|
||||
return json.NewDecoder(NewRSFilterReader(r)).Decode
|
||||
@@ -24,27 +25,38 @@ func NewJSONStreamDecoder(r io.Reader, contentType string) DecoderFn {
|
||||
}
|
||||
}
|
||||
|
||||
// RSFilterReader wraps an io.Reader and filters out ASCII RS characters
|
||||
type RSFilterReader struct {
|
||||
type rsFilterReader struct {
|
||||
reader io.Reader
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
// NewRSFilterReader creates a new RSFilterReader that filters out RS characters
|
||||
func NewRSFilterReader(r io.Reader) *RSFilterReader {
|
||||
return &RSFilterReader{
|
||||
reader: r,
|
||||
buffer: make([]byte, 4096), // Internal buffer for reading chunks
|
||||
}
|
||||
// NewRSFilterReader creates an [io.Reader] that filters out ASCII Record Separators (RS).
|
||||
func NewRSFilterReader(r io.Reader) io.Reader {
|
||||
return &rsFilterReader{reader: r}
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface, filtering out RS characters
|
||||
func (r *RSFilterReader) Read(p []byte) (n int, err error) {
|
||||
func (r *rsFilterReader) Read(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
n, err = r.reader.Read(p)
|
||||
filtered := slices.DeleteFunc(p[:n], func(b byte) bool { return b == rs })
|
||||
return len(filtered), err
|
||||
for {
|
||||
n, err := r.reader.Read(p)
|
||||
if n == 0 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
filtered := slices.DeleteFunc(p[:n], func(b byte) bool { return b == rs })
|
||||
n = len(filtered)
|
||||
if err != nil {
|
||||
if err == io.EOF && n > 0 {
|
||||
return n, nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
if n == 0 {
|
||||
// Avoid returning (0, nil) after consuming input; keep reading until data or an error (e.g., EOF).
|
||||
continue
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
}
|
||||
|
||||
+64
-13
@@ -8,6 +8,8 @@ import (
|
||||
"iter"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/errdefs/pkg/errhttp"
|
||||
|
||||
"github.com/moby/moby/api/types/jsonstream"
|
||||
)
|
||||
|
||||
@@ -44,41 +46,90 @@ func (r Stream) Close() error {
|
||||
|
||||
var _ io.ReadCloser = Stream{}
|
||||
|
||||
// JSONMessages decodes the response stream as a sequence of JSONMessages.
|
||||
// if stream ends or context is cancelled, the underlying [io.Reader] is closed.
|
||||
// JSONMessages decodes the response stream as a sequence of [jsonstream.Message].
|
||||
// The underlying [io.Reader] is closed when the stream ends or if the context
|
||||
// is cancelled.
|
||||
func (r Stream) JSONMessages(ctx context.Context) iter.Seq2[jsonstream.Message, error] {
|
||||
stop := context.AfterFunc(ctx, func() {
|
||||
_ = r.Close()
|
||||
})
|
||||
dec := json.NewDecoder(r)
|
||||
return func(yield func(jsonstream.Message, error) bool) {
|
||||
defer func() {
|
||||
stop() // unregister AfterFunc
|
||||
r.Close()
|
||||
_ = r.Close()
|
||||
}()
|
||||
|
||||
dec := json.NewDecoder(r)
|
||||
for {
|
||||
var jm jsonstream.Message
|
||||
err := dec.Decode(&jm)
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
yield(jm, ctx.Err())
|
||||
if err := dec.Decode(&jm); err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
// Do not return decoding errors if the context was
|
||||
// cancelled, because the decoding errors may be due
|
||||
// to the context being cancelled.
|
||||
yield(jsonstream.Message{}, err)
|
||||
return
|
||||
}
|
||||
yield(jsonstream.Message{}, err)
|
||||
return
|
||||
}
|
||||
if !yield(jm, err) {
|
||||
if !yield(jm, nil) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait waits for operation to complete and detects errors reported as JSONMessage
|
||||
// Wait consumes the stream until completion.
|
||||
//
|
||||
// It returns nil if the operation completes successfully. Errors are
|
||||
// returned if the context is canceled, a decoding/transport failure
|
||||
// occurs, or a JSON message reports an error ([jsonstream.Message.Error]).
|
||||
func (r Stream) Wait(ctx context.Context) error {
|
||||
for _, err := range r.JSONMessages(ctx) {
|
||||
for jm, err := range r.JSONMessages(ctx) {
|
||||
if err != nil {
|
||||
// decode, transport and context cancellation errors.
|
||||
return err
|
||||
}
|
||||
if jm.Error != nil {
|
||||
// push/pull failures.
|
||||
return httpErrorFromStatusCode(jm.Error, jm.Error.Code)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type httpError struct {
|
||||
err error
|
||||
errdef error
|
||||
}
|
||||
|
||||
func (e *httpError) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e *httpError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e *httpError) Is(target error) bool {
|
||||
return errors.Is(e.errdef, target)
|
||||
}
|
||||
|
||||
// httpErrorFromStatusCode creates an errdef error, based on the provided HTTP status-code
|
||||
//
|
||||
// TODO(thaJeztah): unify with the implementation in client and move to an internal package
|
||||
// see https://github.com/moby/moby/blob/client/v0.4.0/client/errors.go#L76-L114
|
||||
func httpErrorFromStatusCode(err error, statusCode int) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &httpError{
|
||||
err: err,
|
||||
errdef: errhttp.ToNative(statusCode),
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -244,12 +244,15 @@ func imageDiskUsageFromLegacyAPI(du *legacyDiskUsage) ImagesDiskUsage {
|
||||
Items: du.Images,
|
||||
}
|
||||
|
||||
for _, i := range idu.Items {
|
||||
if i.Containers > 0 {
|
||||
for _, img := range idu.Items {
|
||||
switch {
|
||||
case img.Containers < 0:
|
||||
// No container-count information available; skip (assume it's in use).
|
||||
case img.Containers > 0:
|
||||
idu.ActiveCount++
|
||||
} else if i.Size != -1 && i.SharedSize != -1 {
|
||||
// Only count reclaimable size if we have size information
|
||||
idu.Reclaimable += (i.Size - i.SharedSize)
|
||||
case img.Containers == 0 && img.Size != -1 && img.SharedSize != -1:
|
||||
reclaimable := img.Size - img.SharedSize
|
||||
idu.Reclaimable += reclaimable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
Vendored
+3
-1
@@ -364,7 +364,9 @@ func (n HTTPServer) MetricAttributes(server string, req *http.Request, statusCod
|
||||
if statusCode > 0 {
|
||||
num++
|
||||
}
|
||||
|
||||
if route == "" && req.Pattern != "" {
|
||||
route = httpRoute(req.Pattern)
|
||||
}
|
||||
if route != "" {
|
||||
num++
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,4 +4,4 @@
|
||||
package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
|
||||
// Version is the current release version of the otelhttp instrumentation.
|
||||
const Version = "0.67.0"
|
||||
const Version = "0.68.0"
|
||||
|
||||
+11
@@ -17,6 +17,7 @@ linters:
|
||||
- ineffassign
|
||||
- misspell
|
||||
- modernize
|
||||
- noctx
|
||||
- perfsprint
|
||||
- revive
|
||||
- staticcheck
|
||||
@@ -88,6 +89,16 @@ linters:
|
||||
deny:
|
||||
- pkg: go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal
|
||||
desc: Do not use cross-module internal packages.
|
||||
semconv:
|
||||
list-mode: lax
|
||||
files:
|
||||
- "!**/semconv/**"
|
||||
- "!**/exporters/zipkin/**"
|
||||
deny:
|
||||
- pkg: go.opentelemetry.io/otel/semconv
|
||||
desc: "Use go.opentelemetry.io/otel/semconv/v1.40.0 instead. If a newer semconv version has been released, update the depguard rule."
|
||||
allow:
|
||||
- go.opentelemetry.io/otel/semconv/v1.40.0
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- appendAssign
|
||||
|
||||
+45
-1
@@ -11,6 +11,49 @@ 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.43.0/0.65.0/0.19.0] 2026-04-02
|
||||
|
||||
### Added
|
||||
|
||||
- Add `IsRandom` and `WithRandom` on `TraceFlags`, and `IsRandom` on `SpanContext` in `go.opentelemetry.io/otel/trace` for [W3C Trace Context Level 2 Random Trace ID Flag](https://www.w3.org/TR/trace-context-2/#random-trace-id-flag) support. (#8012)
|
||||
- Add service detection with `WithService` in `go.opentelemetry.io/otel/sdk/resource`. (#7642)
|
||||
- Add `DefaultWithContext` and `EnvironmentWithContext` in `go.opentelemetry.io/otel/sdk/resource` to support plumbing `context.Context` through default and environment detectors. (#8051)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8038)
|
||||
- Support attributes with empty value (`attribute.EMPTY`) in `go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest`. (#8038)
|
||||
- Add support for per-series start time tracking for cumulative metrics in `go.opentelemetry.io/otel/sdk/metric`.
|
||||
Set `OTEL_GO_X_PER_SERIES_START_TIMESTAMPS=true` to enable. (#8060)
|
||||
- Add `WithCardinalityLimitSelector` for metric reader for configuring cardinality limits specific to the instrument kind. (#7855)
|
||||
|
||||
### Changed
|
||||
|
||||
- Introduce the `EMPTY` Type in `go.opentelemetry.io/otel/attribute` to reflect that an empty value is now a valid value, with `INVALID` remaining as a deprecated alias of `EMPTY`. (#8038)
|
||||
- Improve slice handling in `go.opentelemetry.io/otel/attribute` to optimize short slice values with fixed-size fast paths. (#8039)
|
||||
- Improve performance of span metric recording in `go.opentelemetry.io/otel/sdk/trace` by returning early if self-observability is not enabled. (#8067)
|
||||
- Improve formatting of metric data diffs in `go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest`. (#8073)
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecate `INVALID` in `go.opentelemetry.io/otel/attribute`. Use `EMPTY` instead. (#8038)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Return spec-compliant `TraceIdRatioBased` description. This is a breaking behavioral change, but it is necessary to
|
||||
make the implementation [spec-compliant](https://opentelemetry.io/docs/specs/otel/trace/sdk/#traceidratiobased). (#8027)
|
||||
- Fix a race condition in `go.opentelemetry.io/otel/sdk/metric` where the lastvalue aggregation could collect the value 0 even when no zero-value measurements were recorded. (#8056)
|
||||
- Limit HTTP response body to 4 MiB in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` to mitigate excessive memory usage caused by a misconfigured or malicious server.
|
||||
Responses exceeding the limit are treated as non-retryable errors. (#8108)
|
||||
- Limit HTTP response body to 4 MiB in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` to mitigate excessive memory usage caused by a misconfigured or malicious server.
|
||||
Responses exceeding the limit are treated as non-retryable errors. (#8108)
|
||||
- Limit HTTP response body to 4 MiB in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` to mitigate excessive memory usage caused by a misconfigured or malicious server.
|
||||
Responses exceeding the limit are treated as non-retryable errors. (#8108)
|
||||
- `WithHostID` detector in `go.opentelemetry.io/otel/sdk/resource` to use full path for `kenv` command on BSD. (#8113)
|
||||
- Fix missing `request.GetBody` in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` to correctly handle HTTP2 GOAWAY frame. (#8096)
|
||||
|
||||
## [1.42.0/0.64.0/0.18.0/0.0.16] 2026-03-06
|
||||
|
||||
### Added
|
||||
@@ -3576,7 +3619,8 @@ 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.42.0...HEAD
|
||||
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.43.0...HEAD
|
||||
[1.43.0/0.65.0/0.19.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.43.0
|
||||
[1.42.0/0.64.0/0.18.0/0.0.16]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.42.0
|
||||
[1.41.0/0.63.0/0.17.0/0.0.15]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.41.0
|
||||
[1.40.0/0.62.0/0.16.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.40.0
|
||||
|
||||
+4
@@ -38,10 +38,14 @@ CROSSLINK = $(TOOLS)/crosslink
|
||||
$(TOOLS)/crosslink: PACKAGE=go.opentelemetry.io/build-tools/crosslink
|
||||
|
||||
SEMCONVKIT = $(TOOLS)/semconvkit
|
||||
SEMCONVKIT_FILES := $(sort $(shell find $(TOOLS_MOD_DIR)/semconvkit -type f))
|
||||
$(TOOLS)/semconvkit: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/semconvkit
|
||||
$(TOOLS)/semconvkit: $(SEMCONVKIT_FILES)
|
||||
|
||||
VERIFYREADMES = $(TOOLS)/verifyreadmes
|
||||
VERIFYREADMES_FILES := $(sort $(shell find $(TOOLS_MOD_DIR)/verifyreadmes -type f))
|
||||
$(TOOLS)/verifyreadmes: PACKAGE=go.opentelemetry.io/otel/$(TOOLS_MOD_DIR)/verifyreadmes
|
||||
$(TOOLS)/verifyreadmes: $(VERIFYREADMES_FILES)
|
||||
|
||||
GOLANGCI_LINT = $(TOOLS)/golangci-lint
|
||||
$(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/v2/cmd/golangci-lint
|
||||
|
||||
+40
-1
@@ -4,7 +4,9 @@
|
||||
|
||||
Create a `Version Release` issue to track the release process.
|
||||
|
||||
## Semantic Convention Generation
|
||||
## Semantic Convention Upgrade
|
||||
|
||||
### Semantic Convention Generation
|
||||
|
||||
New versions of the [OpenTelemetry Semantic Conventions] mean new versions of the `semconv` package need to be generated.
|
||||
The `semconv-generate` make target is used for this.
|
||||
@@ -22,6 +24,43 @@ make semconv-generate # Uses the exported TAG.
|
||||
This should create a new sub-package of [`semconv`](./semconv).
|
||||
Ensure things look correct before submitting a pull request to include the addition.
|
||||
|
||||
The `CHANGELOG.md` should also be updated to reflect the new changes:
|
||||
|
||||
```md
|
||||
- The `go.opentelemetry.io/otel/semconv/<NEW VERSION>` package. The package contains semantic conventions from the `<NEW VERSION>` version of the OpenTelemetry Semantic Conventions. See the [migration documentation](./semconv/<NEW VERSION>/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/<PREVIOUS VERSION>`. (#PR_NUMBER)
|
||||
```
|
||||
|
||||
> **Tip:** Change to the release and prior version to match the changes
|
||||
|
||||
### Update semconv imports
|
||||
|
||||
Once the new semconv module has been generated, update all semconv imports throughout the codebase to reference the new version:
|
||||
|
||||
```go
|
||||
// Before
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
|
||||
"go.opentelemetry.io/otel/semconv/v1.37.0/otelconv"
|
||||
|
||||
|
||||
// After
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.39.0"
|
||||
"go.opentelemetry.io/otel/semconv/v1.39.0/otelconv"
|
||||
```
|
||||
|
||||
Once complete, run `make` to check for any compilation or test failures.
|
||||
|
||||
#### Handling attribute changes
|
||||
|
||||
Some semconv releases might add new attributes or impact attributes that are currently being used. Changes could stem from a simple renaming, to more complex changes like merging attributes and property values being changed.
|
||||
|
||||
One should update the code to the new attributes that supersede the impacted ones, hence sticking to the semantic conventions. However, legacy attributes might still be emitted in accordance to the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable.
|
||||
|
||||
For an example on how such migration might have to be tracked and performed, see issue [#7806](https://github.com/open-telemetry/opentelemetry-go/issues/7806).
|
||||
|
||||
### Go contrib linter update
|
||||
|
||||
Update [.golangci.yml](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/.golangci.yml) in [opentelemetry-go-contrib](https://github.com/open-telemetry/opentelemetry-go-contrib/) to mandate the new semconv version.
|
||||
|
||||
## Breaking changes validation
|
||||
|
||||
You can run `make gorelease` which runs [gorelease](https://pkg.go.dev/golang.org/x/exp/cmd/gorelease) to ensure that there are no unwanted changes made in the public API.
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ var (
|
||||
_ Encoder = &defaultAttrEncoder{}
|
||||
|
||||
// encoderIDCounter is for generating IDs for other attribute encoders.
|
||||
encoderIDCounter uint64
|
||||
encoderIDCounter atomic.Uint64
|
||||
|
||||
defaultEncoderOnce sync.Once
|
||||
defaultEncoderID = NewEncoderID()
|
||||
@@ -64,7 +64,7 @@ var (
|
||||
// once per each type of attribute encoder. Preferably in init() or in var
|
||||
// definition.
|
||||
func NewEncoderID() EncoderID {
|
||||
return EncoderID{value: atomic.AddUint64(&encoderIDCounter, 1)}
|
||||
return EncoderID{value: encoderIDCounter.Add(1)}
|
||||
}
|
||||
|
||||
// DefaultEncoder returns an attribute encoder that encodes attributes in such
|
||||
|
||||
+3
-1
@@ -27,6 +27,7 @@ const (
|
||||
int64SliceID uint64 = 3762322556277578591 // "_[]int64" (little endian)
|
||||
float64SliceID uint64 = 7308324551835016539 // "[]double" (little endian)
|
||||
stringSliceID uint64 = 7453010373645655387 // "[]string" (little endian)
|
||||
emptyID uint64 = 7305809155345288421 // "__empty_" (little endian)
|
||||
)
|
||||
|
||||
// hashKVs returns a new xxHash64 hash of kvs.
|
||||
@@ -80,7 +81,8 @@ func hashKV(h xxhash.Hash, kv KeyValue) xxhash.Hash {
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
h = h.String(rv.Index(i).String())
|
||||
}
|
||||
case INVALID:
|
||||
case EMPTY:
|
||||
h = h.Uint64(emptyID)
|
||||
default:
|
||||
// Logging is an alternative, but using the internal logger here
|
||||
// causes an import cycle so it is not done.
|
||||
|
||||
+50
-67
@@ -11,80 +11,63 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// BoolSliceValue converts a bool slice into an array with same elements as slice.
|
||||
func BoolSliceValue(v []bool) any {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[bool]())).Elem()
|
||||
// sliceElem is the exact set of element types stored in attribute slice values.
|
||||
// Using a closed set prevents accidental instantiations for unsupported types.
|
||||
type sliceElem interface {
|
||||
bool | int64 | float64 | string
|
||||
}
|
||||
|
||||
// SliceValue converts a slice into an array with the same elements.
|
||||
func SliceValue[T sliceElem](v []T) any {
|
||||
// Keep only the common tiny-slice cases out of reflection. Extending this
|
||||
// much further increases code size for diminishing benefit while larger
|
||||
// slices still need the generic reflective path to preserve comparability.
|
||||
// This matches the short lengths that show up most often in local
|
||||
// benchmarks and semantic convention examples while leaving larger, less
|
||||
// predictable slices on the generic reflective path.
|
||||
switch len(v) {
|
||||
case 0:
|
||||
return [0]T{}
|
||||
case 1:
|
||||
return [1]T{v[0]}
|
||||
case 2:
|
||||
return [2]T{v[0], v[1]}
|
||||
case 3:
|
||||
return [3]T{v[0], v[1], v[2]}
|
||||
}
|
||||
|
||||
return sliceValueReflect(v)
|
||||
}
|
||||
|
||||
// AsSlice converts an array into a slice with the same elements.
|
||||
func AsSlice[T sliceElem](v any) []T {
|
||||
// Mirror the small fixed-array fast path used by SliceValue.
|
||||
switch a := v.(type) {
|
||||
case [0]T:
|
||||
return []T{}
|
||||
case [1]T:
|
||||
return []T{a[0]}
|
||||
case [2]T:
|
||||
return []T{a[0], a[1]}
|
||||
case [3]T:
|
||||
return []T{a[0], a[1], a[2]}
|
||||
}
|
||||
|
||||
return asSliceReflect[T](v)
|
||||
}
|
||||
|
||||
func sliceValueReflect[T sliceElem](v []T) any {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[T]())).Elem()
|
||||
reflect.Copy(cp, reflect.ValueOf(v))
|
||||
return cp.Interface()
|
||||
}
|
||||
|
||||
// Int64SliceValue converts an int64 slice into an array with same elements as slice.
|
||||
func Int64SliceValue(v []int64) any {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[int64]())).Elem()
|
||||
reflect.Copy(cp, reflect.ValueOf(v))
|
||||
return cp.Interface()
|
||||
}
|
||||
|
||||
// Float64SliceValue converts a float64 slice into an array with same elements as slice.
|
||||
func Float64SliceValue(v []float64) any {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[float64]())).Elem()
|
||||
reflect.Copy(cp, reflect.ValueOf(v))
|
||||
return cp.Interface()
|
||||
}
|
||||
|
||||
// StringSliceValue converts a string slice into an array with same elements as slice.
|
||||
func StringSliceValue(v []string) any {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[string]())).Elem()
|
||||
reflect.Copy(cp, reflect.ValueOf(v))
|
||||
return cp.Interface()
|
||||
}
|
||||
|
||||
// AsBoolSlice converts a bool array into a slice into with same elements as array.
|
||||
func AsBoolSlice(v any) []bool {
|
||||
func asSliceReflect[T sliceElem](v any) []T {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Type().Kind() != reflect.Array {
|
||||
if !rv.IsValid() || rv.Kind() != reflect.Array || rv.Type().Elem() != reflect.TypeFor[T]() {
|
||||
return nil
|
||||
}
|
||||
cpy := make([]bool, rv.Len())
|
||||
if len(cpy) > 0 {
|
||||
_ = reflect.Copy(reflect.ValueOf(cpy), rv)
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
// AsInt64Slice converts an int64 array into a slice into with same elements as array.
|
||||
func AsInt64Slice(v any) []int64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Type().Kind() != reflect.Array {
|
||||
return nil
|
||||
}
|
||||
cpy := make([]int64, rv.Len())
|
||||
if len(cpy) > 0 {
|
||||
_ = reflect.Copy(reflect.ValueOf(cpy), rv)
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
// AsFloat64Slice converts a float64 array into a slice into with same elements as array.
|
||||
func AsFloat64Slice(v any) []float64 {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Type().Kind() != reflect.Array {
|
||||
return nil
|
||||
}
|
||||
cpy := make([]float64, rv.Len())
|
||||
if len(cpy) > 0 {
|
||||
_ = reflect.Copy(reflect.ValueOf(cpy), rv)
|
||||
}
|
||||
return cpy
|
||||
}
|
||||
|
||||
// AsStringSlice converts a string array into a slice into with same elements as array.
|
||||
func AsStringSlice(v any) []string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Type().Kind() != reflect.Array {
|
||||
return nil
|
||||
}
|
||||
cpy := make([]string, rv.Len())
|
||||
cpy := make([]T, rv.Len())
|
||||
if len(cpy) > 0 {
|
||||
_ = reflect.Copy(reflect.ValueOf(cpy), rv)
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ type KeyValue struct {
|
||||
|
||||
// Valid reports whether kv is a valid OpenTelemetry attribute.
|
||||
func (kv KeyValue) Valid() bool {
|
||||
return kv.Key.Defined() && kv.Value.Type() != INVALID
|
||||
return kv.Key.Defined()
|
||||
}
|
||||
|
||||
// Bool creates a KeyValue with a BOOL Value type.
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[INVALID-0]
|
||||
_ = x[EMPTY-0]
|
||||
_ = x[BOOL-1]
|
||||
_ = x[INT64-2]
|
||||
_ = x[FLOAT64-3]
|
||||
@@ -19,9 +19,9 @@ func _() {
|
||||
_ = x[STRINGSLICE-8]
|
||||
}
|
||||
|
||||
const _Type_name = "INVALIDBOOLINT64FLOAT64STRINGBOOLSLICEINT64SLICEFLOAT64SLICESTRINGSLICE"
|
||||
const _Type_name = "EMPTYBOOLINT64FLOAT64STRINGBOOLSLICEINT64SLICEFLOAT64SLICESTRINGSLICE"
|
||||
|
||||
var _Type_index = [...]uint8{0, 7, 11, 16, 23, 29, 38, 48, 60, 71}
|
||||
var _Type_index = [...]uint8{0, 5, 9, 14, 21, 27, 36, 46, 58, 69}
|
||||
|
||||
func (i Type) String() string {
|
||||
idx := int(i) - 0
|
||||
|
||||
+42
-19
@@ -6,7 +6,6 @@ package attribute // import "go.opentelemetry.io/otel/attribute"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
attribute "go.opentelemetry.io/otel/attribute/internal"
|
||||
@@ -18,6 +17,8 @@ import (
|
||||
type Type int // nolint: revive // redefines builtin Type.
|
||||
|
||||
// Value represents the value part in key-value pairs.
|
||||
//
|
||||
// Note that the zero value is a valid empty value.
|
||||
type Value struct {
|
||||
vtype Type
|
||||
numeric uint64
|
||||
@@ -26,8 +27,8 @@ type Value struct {
|
||||
}
|
||||
|
||||
const (
|
||||
// INVALID is used for a Value with no value set.
|
||||
INVALID Type = iota
|
||||
// EMPTY is used for a Value with no value set.
|
||||
EMPTY Type = iota
|
||||
// BOOL is a boolean Type Value.
|
||||
BOOL
|
||||
// INT64 is a 64-bit signed integral Type Value.
|
||||
@@ -44,6 +45,10 @@ const (
|
||||
FLOAT64SLICE
|
||||
// STRINGSLICE is a slice of strings Type Value.
|
||||
STRINGSLICE
|
||||
// INVALID is used for a Value with no value set.
|
||||
//
|
||||
// Deprecated: Use EMPTY instead as an empty value is a valid value.
|
||||
INVALID = EMPTY
|
||||
)
|
||||
|
||||
// BoolValue creates a BOOL Value.
|
||||
@@ -56,7 +61,7 @@ func BoolValue(v bool) Value {
|
||||
|
||||
// BoolSliceValue creates a BOOLSLICE Value.
|
||||
func BoolSliceValue(v []bool) Value {
|
||||
return Value{vtype: BOOLSLICE, slice: attribute.BoolSliceValue(v)}
|
||||
return Value{vtype: BOOLSLICE, slice: attribute.SliceValue(v)}
|
||||
}
|
||||
|
||||
// IntValue creates an INT64 Value.
|
||||
@@ -64,16 +69,30 @@ func IntValue(v int) Value {
|
||||
return Int64Value(int64(v))
|
||||
}
|
||||
|
||||
// IntSliceValue creates an INTSLICE Value.
|
||||
// IntSliceValue creates an INT64SLICE Value.
|
||||
func IntSliceValue(v []int) Value {
|
||||
cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeFor[int64]()))
|
||||
for i, val := range v {
|
||||
cp.Elem().Index(i).SetInt(int64(val))
|
||||
}
|
||||
return Value{
|
||||
vtype: INT64SLICE,
|
||||
slice: cp.Elem().Interface(),
|
||||
val := Value{vtype: INT64SLICE}
|
||||
|
||||
// Avoid the common tiny-slice cases from allocating a new slice.
|
||||
switch len(v) {
|
||||
case 0:
|
||||
val.slice = [0]int64{}
|
||||
case 1:
|
||||
val.slice = [1]int64{int64(v[0])}
|
||||
case 2:
|
||||
val.slice = [2]int64{int64(v[0]), int64(v[1])}
|
||||
case 3:
|
||||
val.slice = [3]int64{int64(v[0]), int64(v[1]), int64(v[2])}
|
||||
default:
|
||||
// Fallback to a new slice for larger slices.
|
||||
cp := make([]int64, len(v))
|
||||
for i, val := range v {
|
||||
cp[i] = int64(val)
|
||||
}
|
||||
val.slice = attribute.SliceValue(cp)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
// Int64Value creates an INT64 Value.
|
||||
@@ -86,7 +105,7 @@ func Int64Value(v int64) Value {
|
||||
|
||||
// Int64SliceValue creates an INT64SLICE Value.
|
||||
func Int64SliceValue(v []int64) Value {
|
||||
return Value{vtype: INT64SLICE, slice: attribute.Int64SliceValue(v)}
|
||||
return Value{vtype: INT64SLICE, slice: attribute.SliceValue(v)}
|
||||
}
|
||||
|
||||
// Float64Value creates a FLOAT64 Value.
|
||||
@@ -99,7 +118,7 @@ func Float64Value(v float64) Value {
|
||||
|
||||
// Float64SliceValue creates a FLOAT64SLICE Value.
|
||||
func Float64SliceValue(v []float64) Value {
|
||||
return Value{vtype: FLOAT64SLICE, slice: attribute.Float64SliceValue(v)}
|
||||
return Value{vtype: FLOAT64SLICE, slice: attribute.SliceValue(v)}
|
||||
}
|
||||
|
||||
// StringValue creates a STRING Value.
|
||||
@@ -112,7 +131,7 @@ func StringValue(v string) Value {
|
||||
|
||||
// StringSliceValue creates a STRINGSLICE Value.
|
||||
func StringSliceValue(v []string) Value {
|
||||
return Value{vtype: STRINGSLICE, slice: attribute.StringSliceValue(v)}
|
||||
return Value{vtype: STRINGSLICE, slice: attribute.SliceValue(v)}
|
||||
}
|
||||
|
||||
// Type returns a type of the Value.
|
||||
@@ -136,7 +155,7 @@ func (v Value) AsBoolSlice() []bool {
|
||||
}
|
||||
|
||||
func (v Value) asBoolSlice() []bool {
|
||||
return attribute.AsBoolSlice(v.slice)
|
||||
return attribute.AsSlice[bool](v.slice)
|
||||
}
|
||||
|
||||
// AsInt64 returns the int64 value. Make sure that the Value's type is
|
||||
@@ -155,7 +174,7 @@ func (v Value) AsInt64Slice() []int64 {
|
||||
}
|
||||
|
||||
func (v Value) asInt64Slice() []int64 {
|
||||
return attribute.AsInt64Slice(v.slice)
|
||||
return attribute.AsSlice[int64](v.slice)
|
||||
}
|
||||
|
||||
// AsFloat64 returns the float64 value. Make sure that the Value's
|
||||
@@ -174,7 +193,7 @@ func (v Value) AsFloat64Slice() []float64 {
|
||||
}
|
||||
|
||||
func (v Value) asFloat64Slice() []float64 {
|
||||
return attribute.AsFloat64Slice(v.slice)
|
||||
return attribute.AsSlice[float64](v.slice)
|
||||
}
|
||||
|
||||
// AsString returns the string value. Make sure that the Value's type
|
||||
@@ -193,7 +212,7 @@ func (v Value) AsStringSlice() []string {
|
||||
}
|
||||
|
||||
func (v Value) asStringSlice() []string {
|
||||
return attribute.AsStringSlice(v.slice)
|
||||
return attribute.AsSlice[string](v.slice)
|
||||
}
|
||||
|
||||
type unknownValueType struct{}
|
||||
@@ -217,6 +236,8 @@ func (v Value) AsInterface() any {
|
||||
return v.stringly
|
||||
case STRINGSLICE:
|
||||
return v.asStringSlice()
|
||||
case EMPTY:
|
||||
return nil
|
||||
}
|
||||
return unknownValueType{}
|
||||
}
|
||||
@@ -252,6 +273,8 @@ func (v Value) Emit() string {
|
||||
return string(j)
|
||||
case STRING:
|
||||
return v.stringly
|
||||
case EMPTY:
|
||||
return ""
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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.21.2@sha256:2401de985c38bdb98b43918e2f43aa36b2afed4aa5669ac1c1de0a17301cd36d AS weaver
|
||||
FROM otel/weaver:v0.22.1@sha256:33ae522ae4b71c1c562563c1d81f46aa0f79f088a0873199143a1f11ac30e5c9 AS weaver
|
||||
FROM avtodev/markdown-lint:v1@sha256:6aeedc2f49138ce7a1cd0adffc1b1c0321b841dc2102408967d9301c031949ee AS markdown
|
||||
|
||||
Generated
Vendored
+1
@@ -87,6 +87,7 @@ func Value(v attribute.Value) *cpb.AnyValue {
|
||||
Values: stringSliceValues(v.AsStringSlice()),
|
||||
},
|
||||
}
|
||||
case attribute.EMPTY:
|
||||
default:
|
||||
av.Value = &cpb.AnyValue_StringValue{
|
||||
StringValue: "INVALID",
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -5,5 +5,5 @@ package otlpmetricgrpc // import "go.opentelemetry.io/otel/exporters/otlp/otlpme
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP over gRPC metrics exporter in use.
|
||||
func Version() string {
|
||||
return "1.42.0"
|
||||
return "1.43.0"
|
||||
}
|
||||
|
||||
Generated
Vendored
+1
@@ -93,6 +93,7 @@ func Value(v attribute.Value) *commonpb.AnyValue {
|
||||
Values: stringSliceValues(v.AsStringSlice()),
|
||||
},
|
||||
}
|
||||
case attribute.EMPTY:
|
||||
default:
|
||||
av.Value = &commonpb.AnyValue_StringValue{
|
||||
StringValue: "INVALID",
|
||||
|
||||
Generated
Vendored
+1
-1
@@ -5,4 +5,4 @@ package internal // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/ot
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP gRPC trace
|
||||
// exporter in use.
|
||||
const Version = "1.42.0"
|
||||
const Version = "1.43.0"
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
|
||||
// Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
|
||||
func Version() string {
|
||||
return "1.42.0"
|
||||
return "1.43.0"
|
||||
}
|
||||
|
||||
+15
@@ -37,3 +37,18 @@ var Observability = newFeature(
|
||||
return "", false
|
||||
},
|
||||
)
|
||||
|
||||
// PerSeriesStartTimestamps is an experimental feature flag that determines if the SDK
|
||||
// uses the new Start Timestamps specification.
|
||||
//
|
||||
// To enable this feature set the OTEL_GO_X_PER_SERIES_START_TIMESTAMPS environment variable
|
||||
// to the case-insensitive string value of "true".
|
||||
var PerSeriesStartTimestamps = newFeature(
|
||||
[]string{"PER_SERIES_START_TIMESTAMPS"},
|
||||
func(v string) (bool, bool) {
|
||||
if strings.EqualFold(v, "true") {
|
||||
return true, true
|
||||
}
|
||||
return false, false
|
||||
},
|
||||
)
|
||||
|
||||
+3
-1
@@ -160,12 +160,14 @@ func WithExemplarFilter(filter exemplar.Filter) Option {
|
||||
})
|
||||
}
|
||||
|
||||
// WithCardinalityLimit sets the cardinality limit for the MeterProvider.
|
||||
// WithCardinalityLimit sets the global cardinality limit for the MeterProvider.
|
||||
//
|
||||
// The cardinality limit is the hard limit on the number of metric datapoints
|
||||
// that can be collected for a single instrument in a single collect cycle.
|
||||
//
|
||||
// Setting this to a zero or negative value means no limit is applied.
|
||||
// This value applies to all instrument kinds, but can be overridden per kind by
|
||||
// the reader's cardinality limit selector (see [WithCardinalityLimitSelector]).
|
||||
func WithCardinalityLimit(limit int) Option {
|
||||
// For backward compatibility, the environment variable `OTEL_GO_X_CARDINALITY_LIMIT`
|
||||
// can also be used to set this value.
|
||||
|
||||
Generated
Vendored
+82
-69
@@ -8,10 +8,12 @@ import (
|
||||
"errors"
|
||||
"math"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
)
|
||||
|
||||
@@ -20,11 +22,6 @@ const (
|
||||
expoMinScale = -10
|
||||
|
||||
smallestNonZeroNormalFloat64 = 0x1p-1022
|
||||
|
||||
// These redefine the Math constants with a type, so the compiler won't coerce
|
||||
// them into an int on 32 bit platforms.
|
||||
maxInt64 int64 = math.MaxInt64
|
||||
minInt64 int64 = math.MinInt64
|
||||
)
|
||||
|
||||
// expoHistogramDataPoint is a single data point in an exponential histogram.
|
||||
@@ -32,19 +29,19 @@ type expoHistogramDataPoint[N int64 | float64] struct {
|
||||
attrs attribute.Set
|
||||
res FilteredExemplarReservoir[N]
|
||||
|
||||
min N
|
||||
max N
|
||||
sum N
|
||||
minMax atomicMinMax[N]
|
||||
sum atomicCounter[N]
|
||||
|
||||
maxSize int
|
||||
noMinMax bool
|
||||
noSum bool
|
||||
|
||||
scale int32
|
||||
scale atomic.Int32
|
||||
|
||||
posBuckets expoBuckets
|
||||
negBuckets expoBuckets
|
||||
zeroCount uint64
|
||||
zeroCount atomic.Uint64
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
func newExpoHistogramDataPoint[N int64 | float64](
|
||||
@@ -53,42 +50,30 @@ func newExpoHistogramDataPoint[N int64 | float64](
|
||||
maxScale int32,
|
||||
noMinMax, noSum bool,
|
||||
) *expoHistogramDataPoint[N] { // nolint:revive // we need this control flag
|
||||
f := math.MaxFloat64
|
||||
ma := N(f) // if N is int64, max will overflow to -9223372036854775808
|
||||
mi := N(-f)
|
||||
if N(maxInt64) > N(f) {
|
||||
ma = N(maxInt64)
|
||||
mi = N(minInt64)
|
||||
}
|
||||
return &expoHistogramDataPoint[N]{
|
||||
attrs: attrs,
|
||||
min: ma,
|
||||
max: mi,
|
||||
maxSize: maxSize,
|
||||
noMinMax: noMinMax,
|
||||
noSum: noSum,
|
||||
scale: maxScale,
|
||||
dp := &expoHistogramDataPoint[N]{
|
||||
attrs: attrs,
|
||||
maxSize: maxSize,
|
||||
noMinMax: noMinMax,
|
||||
noSum: noSum,
|
||||
startTime: now(),
|
||||
}
|
||||
dp.scale.Store(maxScale)
|
||||
return dp
|
||||
}
|
||||
|
||||
// record adds a new measurement to the histogram. It will rescale the buckets if needed.
|
||||
func (p *expoHistogramDataPoint[N]) record(v N) {
|
||||
if !p.noMinMax {
|
||||
if v < p.min {
|
||||
p.min = v
|
||||
}
|
||||
if v > p.max {
|
||||
p.max = v
|
||||
}
|
||||
p.minMax.Update(v)
|
||||
}
|
||||
if !p.noSum {
|
||||
p.sum += v
|
||||
p.sum.add(v)
|
||||
}
|
||||
|
||||
absV := math.Abs(float64(v))
|
||||
|
||||
if float64(absV) == 0.0 {
|
||||
p.zeroCount++
|
||||
p.zeroCount.Add(1)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,14 +87,15 @@ func (p *expoHistogramDataPoint[N]) record(v N) {
|
||||
// If the new bin would make the counts larger than maxScale, we need to
|
||||
// downscale current measurements.
|
||||
if scaleDelta := p.scaleChange(bin, bucket.startBin, len(bucket.counts)); scaleDelta > 0 {
|
||||
if p.scale-scaleDelta < expoMinScale {
|
||||
currentScale := p.scale.Load()
|
||||
if currentScale-scaleDelta < expoMinScale {
|
||||
// With a scale of -10 there is only two buckets for the whole range of float64 values.
|
||||
// This can only happen if there is a max size of 1.
|
||||
otel.Handle(errors.New("exponential histogram scale underflow"))
|
||||
return
|
||||
}
|
||||
// Downscale
|
||||
p.scale -= scaleDelta
|
||||
p.scale.Add(-scaleDelta)
|
||||
p.posBuckets.downscale(scaleDelta)
|
||||
p.negBuckets.downscale(scaleDelta)
|
||||
|
||||
@@ -124,7 +110,8 @@ func (p *expoHistogramDataPoint[N]) getBin(v float64) int32 {
|
||||
frac, expInt := math.Frexp(v)
|
||||
// 11-bit exponential.
|
||||
exp := int32(expInt) // nolint: gosec
|
||||
if p.scale <= 0 {
|
||||
scale := p.scale.Load()
|
||||
if scale <= 0 {
|
||||
// Because of the choice of fraction is always 1 power of two higher than we want.
|
||||
var correction int32 = 1
|
||||
if frac == .5 {
|
||||
@@ -132,9 +119,9 @@ func (p *expoHistogramDataPoint[N]) getBin(v float64) int32 {
|
||||
// will be one higher than we want.
|
||||
correction = 2
|
||||
}
|
||||
return (exp - correction) >> (-p.scale)
|
||||
return (exp - correction) >> (-scale)
|
||||
}
|
||||
return exp<<p.scale + int32(math.Log(frac)*scaleFactors[p.scale]) - 1
|
||||
return exp<<scale + int32(math.Log(frac)*scaleFactors[scale]) - 1
|
||||
}
|
||||
|
||||
// scaleFactors are constants used in calculating the logarithm index. They are
|
||||
@@ -191,20 +178,21 @@ func (p *expoHistogramDataPoint[N]) scaleChange(bin, startBin int32, length int)
|
||||
}
|
||||
|
||||
func (p *expoHistogramDataPoint[N]) count() uint64 {
|
||||
return p.posBuckets.count() + p.negBuckets.count() + p.zeroCount
|
||||
return p.posBuckets.count() + p.negBuckets.count() + p.zeroCount.Load()
|
||||
}
|
||||
|
||||
// expoBuckets is a set of buckets in an exponential histogram.
|
||||
type expoBuckets struct {
|
||||
startBin int32
|
||||
counts []uint64
|
||||
counts []atomic.Uint64
|
||||
}
|
||||
|
||||
// record increments the count for the given bin, and expands the buckets if needed.
|
||||
// Size changes must be done before calling this function.
|
||||
func (b *expoBuckets) record(bin int32) {
|
||||
if len(b.counts) == 0 {
|
||||
b.counts = []uint64{1}
|
||||
b.counts = make([]atomic.Uint64, 1)
|
||||
b.counts[0].Store(1)
|
||||
b.startBin = bin
|
||||
return
|
||||
}
|
||||
@@ -213,7 +201,7 @@ func (b *expoBuckets) record(bin int32) {
|
||||
|
||||
// if the new bin is inside the current range
|
||||
if bin >= b.startBin && int(bin) <= endBin {
|
||||
b.counts[bin-b.startBin]++
|
||||
b.counts[bin-b.startBin].Add(1)
|
||||
return
|
||||
}
|
||||
// if the new bin is before the current start add spaces to the counts
|
||||
@@ -223,16 +211,22 @@ func (b *expoBuckets) record(bin int32) {
|
||||
shift := b.startBin - bin
|
||||
|
||||
if newLength > cap(b.counts) {
|
||||
b.counts = append(b.counts, make([]uint64, newLength-len(b.counts))...)
|
||||
b.counts = append(b.counts, make([]atomic.Uint64, newLength-len(b.counts))...)
|
||||
}
|
||||
|
||||
copy(b.counts[shift:origLen+int(shift)], b.counts)
|
||||
b.counts = b.counts[:newLength]
|
||||
|
||||
// Shift existing elements to the right. Go's copy() doesn't work for
|
||||
// structs like atomic.Uint64.
|
||||
for i := origLen - 1; i >= 0; i-- {
|
||||
b.counts[i+int(shift)].Store(b.counts[i].Load())
|
||||
}
|
||||
|
||||
for i := 1; i < int(shift); i++ {
|
||||
b.counts[i] = 0
|
||||
b.counts[i].Store(0)
|
||||
}
|
||||
b.startBin = bin
|
||||
b.counts[0] = 1
|
||||
b.counts[0].Store(1)
|
||||
return
|
||||
}
|
||||
// if the new is after the end add spaces to the end
|
||||
@@ -240,15 +234,15 @@ func (b *expoBuckets) record(bin int32) {
|
||||
if int(bin-b.startBin) < cap(b.counts) {
|
||||
b.counts = b.counts[:bin-b.startBin+1]
|
||||
for i := endBin + 1 - int(b.startBin); i < len(b.counts); i++ {
|
||||
b.counts[i] = 0
|
||||
b.counts[i].Store(0)
|
||||
}
|
||||
b.counts[bin-b.startBin] = 1
|
||||
b.counts[bin-b.startBin].Store(1)
|
||||
return
|
||||
}
|
||||
|
||||
end := make([]uint64, int(bin-b.startBin)-len(b.counts)+1)
|
||||
end := make([]atomic.Uint64, int(bin-b.startBin)-len(b.counts)+1)
|
||||
b.counts = append(b.counts, end...)
|
||||
b.counts[bin-b.startBin] = 1
|
||||
b.counts[bin-b.startBin].Store(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,10 +269,10 @@ func (b *expoBuckets) downscale(delta int32) {
|
||||
for i := 1; i < len(b.counts); i++ {
|
||||
idx := i + int(offset)
|
||||
if idx%int(steps) == 0 {
|
||||
b.counts[idx/int(steps)] = b.counts[i]
|
||||
b.counts[idx/int(steps)].Store(b.counts[i].Load())
|
||||
continue
|
||||
}
|
||||
b.counts[idx/int(steps)] += b.counts[i]
|
||||
b.counts[idx/int(steps)].Add(b.counts[i].Load())
|
||||
}
|
||||
|
||||
lastIdx := (len(b.counts) - 1 + int(offset)) / int(steps)
|
||||
@@ -288,8 +282,8 @@ func (b *expoBuckets) downscale(delta int32) {
|
||||
|
||||
func (b *expoBuckets) count() uint64 {
|
||||
var total uint64
|
||||
for _, count := range b.counts {
|
||||
total += count
|
||||
for i := range b.counts {
|
||||
total += b.counts[i].Load()
|
||||
}
|
||||
return total
|
||||
}
|
||||
@@ -386,8 +380,8 @@ func (e *expoHistogram[N]) delta(
|
||||
hDPts[i].StartTime = e.start
|
||||
hDPts[i].Time = t
|
||||
hDPts[i].Count = val.count()
|
||||
hDPts[i].Scale = val.scale
|
||||
hDPts[i].ZeroCount = val.zeroCount
|
||||
hDPts[i].Scale = val.scale.Load()
|
||||
hDPts[i].ZeroCount = val.zeroCount.Load()
|
||||
hDPts[i].ZeroThreshold = 0.0
|
||||
|
||||
hDPts[i].PositiveBucket.Offset = val.posBuckets.startBin
|
||||
@@ -396,7 +390,9 @@ func (e *expoHistogram[N]) delta(
|
||||
len(val.posBuckets.counts),
|
||||
len(val.posBuckets.counts),
|
||||
)
|
||||
copy(hDPts[i].PositiveBucket.Counts, val.posBuckets.counts)
|
||||
for j := range val.posBuckets.counts {
|
||||
hDPts[i].PositiveBucket.Counts[j] = val.posBuckets.counts[j].Load()
|
||||
}
|
||||
|
||||
hDPts[i].NegativeBucket.Offset = val.negBuckets.startBin
|
||||
hDPts[i].NegativeBucket.Counts = reset(
|
||||
@@ -404,14 +400,18 @@ func (e *expoHistogram[N]) delta(
|
||||
len(val.negBuckets.counts),
|
||||
len(val.negBuckets.counts),
|
||||
)
|
||||
copy(hDPts[i].NegativeBucket.Counts, val.negBuckets.counts)
|
||||
for j := range val.negBuckets.counts {
|
||||
hDPts[i].NegativeBucket.Counts[j] = val.negBuckets.counts[j].Load()
|
||||
}
|
||||
|
||||
if !e.noSum {
|
||||
hDPts[i].Sum = val.sum
|
||||
hDPts[i].Sum = val.sum.load()
|
||||
}
|
||||
if !e.noMinMax {
|
||||
hDPts[i].Min = metricdata.NewExtrema(val.min)
|
||||
hDPts[i].Max = metricdata.NewExtrema(val.max)
|
||||
if val.minMax.set.Load() {
|
||||
hDPts[i].Min = metricdata.NewExtrema(val.minMax.minimum.Load())
|
||||
hDPts[i].Max = metricdata.NewExtrema(val.minMax.maximum.Load())
|
||||
}
|
||||
}
|
||||
|
||||
collectExemplars(&hDPts[i].Exemplars, val.res.Collect)
|
||||
@@ -443,14 +443,21 @@ func (e *expoHistogram[N]) cumulative(
|
||||
n := len(e.values)
|
||||
hDPts := reset(h.DataPoints, n, n)
|
||||
|
||||
perSeriesStartTimeEnabled := x.PerSeriesStartTimestamps.Enabled()
|
||||
|
||||
var i int
|
||||
for _, val := range e.values {
|
||||
hDPts[i].Attributes = val.attrs
|
||||
hDPts[i].StartTime = e.start
|
||||
|
||||
startTime := e.start
|
||||
if perSeriesStartTimeEnabled {
|
||||
startTime = val.startTime
|
||||
}
|
||||
hDPts[i].StartTime = startTime
|
||||
hDPts[i].Time = t
|
||||
hDPts[i].Count = val.count()
|
||||
hDPts[i].Scale = val.scale
|
||||
hDPts[i].ZeroCount = val.zeroCount
|
||||
hDPts[i].Scale = val.scale.Load()
|
||||
hDPts[i].ZeroCount = val.zeroCount.Load()
|
||||
hDPts[i].ZeroThreshold = 0.0
|
||||
|
||||
hDPts[i].PositiveBucket.Offset = val.posBuckets.startBin
|
||||
@@ -459,7 +466,9 @@ func (e *expoHistogram[N]) cumulative(
|
||||
len(val.posBuckets.counts),
|
||||
len(val.posBuckets.counts),
|
||||
)
|
||||
copy(hDPts[i].PositiveBucket.Counts, val.posBuckets.counts)
|
||||
for j := range val.posBuckets.counts {
|
||||
hDPts[i].PositiveBucket.Counts[j] = val.posBuckets.counts[j].Load()
|
||||
}
|
||||
|
||||
hDPts[i].NegativeBucket.Offset = val.negBuckets.startBin
|
||||
hDPts[i].NegativeBucket.Counts = reset(
|
||||
@@ -467,14 +476,18 @@ func (e *expoHistogram[N]) cumulative(
|
||||
len(val.negBuckets.counts),
|
||||
len(val.negBuckets.counts),
|
||||
)
|
||||
copy(hDPts[i].NegativeBucket.Counts, val.negBuckets.counts)
|
||||
for j := range val.negBuckets.counts {
|
||||
hDPts[i].NegativeBucket.Counts[j] = val.negBuckets.counts[j].Load()
|
||||
}
|
||||
|
||||
if !e.noSum {
|
||||
hDPts[i].Sum = val.sum
|
||||
hDPts[i].Sum = val.sum.load()
|
||||
}
|
||||
if !e.noMinMax {
|
||||
hDPts[i].Min = metricdata.NewExtrema(val.min)
|
||||
hDPts[i].Max = metricdata.NewExtrema(val.max)
|
||||
if val.minMax.set.Load() {
|
||||
hDPts[i].Min = metricdata.NewExtrema(val.minMax.minimum.Load())
|
||||
hDPts[i].Max = metricdata.NewExtrema(val.minMax.maximum.Load())
|
||||
}
|
||||
}
|
||||
|
||||
collectExemplars(&hDPts[i].Exemplars, val.res.Collect)
|
||||
|
||||
+13
-3
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
)
|
||||
|
||||
@@ -27,8 +28,9 @@ type hotColdHistogramPoint[N int64 | float64] struct {
|
||||
hcwg hotColdWaitGroup
|
||||
hotColdPoint [2]histogramPointCounters[N]
|
||||
|
||||
attrs attribute.Set
|
||||
res FilteredExemplarReservoir[N]
|
||||
attrs attribute.Set
|
||||
res FilteredExemplarReservoir[N]
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
// histogramPointCounters contains only the atomic counter data, and is used by
|
||||
@@ -298,6 +300,7 @@ func (s *cumulativeHistogram[N]) measure(
|
||||
counts: make([]atomic.Uint64, len(s.bounds)+1),
|
||||
},
|
||||
},
|
||||
startTime: now(),
|
||||
}
|
||||
return hPt
|
||||
}).(*hotColdHistogramPoint[N])
|
||||
@@ -339,16 +342,23 @@ func (s *cumulativeHistogram[N]) collect(
|
||||
// current length for capacity.
|
||||
hDPts := reset(h.DataPoints, 0, s.values.Len())
|
||||
|
||||
perSeriesStartTimeEnabled := x.PerSeriesStartTimestamps.Enabled()
|
||||
|
||||
var i int
|
||||
s.values.Range(func(_, value any) bool {
|
||||
val := value.(*hotColdHistogramPoint[N])
|
||||
|
||||
startTime := s.start
|
||||
if perSeriesStartTimeEnabled {
|
||||
startTime = val.startTime
|
||||
}
|
||||
// swap, observe, and clear the point
|
||||
readIdx := val.hcwg.swapHotAndWait()
|
||||
var bucketCounts []uint64
|
||||
count := val.hotColdPoint[readIdx].loadCountsInto(&bucketCounts)
|
||||
newPt := metricdata.HistogramDataPoint[N]{
|
||||
Attributes: val.attrs,
|
||||
StartTime: s.start,
|
||||
StartTime: startTime,
|
||||
Time: t,
|
||||
Count: count,
|
||||
Bounds: bounds,
|
||||
|
||||
+19
-7
@@ -8,14 +8,16 @@ import (
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
)
|
||||
|
||||
// lastValuePoint is timestamped measurement data.
|
||||
type lastValuePoint[N int64 | float64] struct {
|
||||
attrs attribute.Set
|
||||
value atomicN[N]
|
||||
res FilteredExemplarReservoir[N]
|
||||
attrs attribute.Set
|
||||
value atomicN[N]
|
||||
res FilteredExemplarReservoir[N]
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
// lastValueMap summarizes a set of measurements as the last one made.
|
||||
@@ -31,10 +33,13 @@ func (s *lastValueMap[N]) measure(
|
||||
droppedAttr []attribute.KeyValue,
|
||||
) {
|
||||
lv := s.values.LoadOrStoreAttr(fltrAttr, func(attr attribute.Set) any {
|
||||
return &lastValuePoint[N]{
|
||||
res: s.newRes(attr),
|
||||
attrs: attr,
|
||||
p := &lastValuePoint[N]{
|
||||
res: s.newRes(attr),
|
||||
attrs: attr,
|
||||
startTime: now(),
|
||||
}
|
||||
p.value.Store(value)
|
||||
return p
|
||||
}).(*lastValuePoint[N])
|
||||
|
||||
lv.value.Store(value)
|
||||
@@ -156,12 +161,19 @@ func (s *cumulativeLastValue[N]) collect(
|
||||
// current length for capacity.
|
||||
dPts := reset(gData.DataPoints, 0, s.values.Len())
|
||||
|
||||
perSeriesStartTimeEnabled := x.PerSeriesStartTimestamps.Enabled()
|
||||
|
||||
var i int
|
||||
s.values.Range(func(_, value any) bool {
|
||||
v := value.(*lastValuePoint[N])
|
||||
|
||||
startTime := s.start
|
||||
if perSeriesStartTimeEnabled {
|
||||
startTime = v.startTime
|
||||
}
|
||||
newPt := metricdata.DataPoint[N]{
|
||||
Attributes: v.attrs,
|
||||
StartTime: s.start,
|
||||
StartTime: startTime,
|
||||
Time: t,
|
||||
Value: v.value.Load(),
|
||||
}
|
||||
|
||||
+16
-6
@@ -8,13 +8,15 @@ import (
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||
)
|
||||
|
||||
type sumValue[N int64 | float64] struct {
|
||||
n atomicCounter[N]
|
||||
res FilteredExemplarReservoir[N]
|
||||
attrs attribute.Set
|
||||
n atomicCounter[N]
|
||||
res FilteredExemplarReservoir[N]
|
||||
attrs attribute.Set
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
type sumValueMap[N int64 | float64] struct {
|
||||
@@ -30,8 +32,9 @@ func (s *sumValueMap[N]) measure(
|
||||
) {
|
||||
sv := s.values.LoadOrStoreAttr(fltrAttr, func(attr attribute.Set) any {
|
||||
return &sumValue[N]{
|
||||
res: s.newRes(attr),
|
||||
attrs: attr,
|
||||
res: s.newRes(attr),
|
||||
attrs: attr,
|
||||
startTime: now(),
|
||||
}
|
||||
}).(*sumValue[N])
|
||||
sv.n.add(value)
|
||||
@@ -160,12 +163,19 @@ func (s *cumulativeSum[N]) collect(
|
||||
// current length for capacity.
|
||||
dPts := reset(sData.DataPoints, 0, s.values.Len())
|
||||
|
||||
perSeriesStartTimeEnabled := x.PerSeriesStartTimestamps.Enabled()
|
||||
|
||||
var i int
|
||||
s.values.Range(func(_, value any) bool {
|
||||
val := value.(*sumValue[N])
|
||||
|
||||
startTime := s.start
|
||||
if perSeriesStartTimeEnabled {
|
||||
startTime = val.startTime
|
||||
}
|
||||
newPt := metricdata.DataPoint[N]{
|
||||
Attributes: val.attrs,
|
||||
StartTime: s.start,
|
||||
StartTime: startTime,
|
||||
Time: t,
|
||||
Value: val.n.load(),
|
||||
}
|
||||
|
||||
+18
-9
@@ -32,8 +32,9 @@ type ManualReader struct {
|
||||
isShutdown bool
|
||||
externalProducers atomic.Value
|
||||
|
||||
temporalitySelector TemporalitySelector
|
||||
aggregationSelector AggregationSelector
|
||||
temporalitySelector TemporalitySelector
|
||||
aggregationSelector AggregationSelector
|
||||
cardinalityLimitSelector CardinalityLimitSelector
|
||||
|
||||
inst *observ.Instrumentation
|
||||
}
|
||||
@@ -45,8 +46,9 @@ var _ = map[Reader]struct{}{&ManualReader{}: {}}
|
||||
func NewManualReader(opts ...ManualReaderOption) *ManualReader {
|
||||
cfg := newManualReaderConfig(opts)
|
||||
r := &ManualReader{
|
||||
temporalitySelector: cfg.temporalitySelector,
|
||||
aggregationSelector: cfg.aggregationSelector,
|
||||
temporalitySelector: cfg.temporalitySelector,
|
||||
aggregationSelector: cfg.aggregationSelector,
|
||||
cardinalityLimitSelector: cfg.cardinalityLimitSelector,
|
||||
}
|
||||
r.externalProducers.Store(cfg.producers)
|
||||
|
||||
@@ -89,6 +91,11 @@ func (mr *ManualReader) aggregation(
|
||||
return mr.aggregationSelector(kind)
|
||||
}
|
||||
|
||||
// cardinalityLimit returns the cardinality limit for kind.
|
||||
func (mr *ManualReader) cardinalityLimit(kind InstrumentKind) (int, bool) {
|
||||
return mr.cardinalityLimitSelector(kind)
|
||||
}
|
||||
|
||||
// Shutdown closes any connections and frees any resources used by the reader.
|
||||
//
|
||||
// This method is safe to call concurrently.
|
||||
@@ -179,16 +186,18 @@ func (r *ManualReader) MarshalLog() any {
|
||||
|
||||
// manualReaderConfig contains configuration options for a ManualReader.
|
||||
type manualReaderConfig struct {
|
||||
temporalitySelector TemporalitySelector
|
||||
aggregationSelector AggregationSelector
|
||||
producers []Producer
|
||||
temporalitySelector TemporalitySelector
|
||||
aggregationSelector AggregationSelector
|
||||
cardinalityLimitSelector CardinalityLimitSelector
|
||||
producers []Producer
|
||||
}
|
||||
|
||||
// newManualReaderConfig returns a manualReaderConfig configured with options.
|
||||
func newManualReaderConfig(opts []ManualReaderOption) manualReaderConfig {
|
||||
cfg := manualReaderConfig{
|
||||
temporalitySelector: DefaultTemporalitySelector,
|
||||
aggregationSelector: DefaultAggregationSelector,
|
||||
temporalitySelector: DefaultTemporalitySelector,
|
||||
aggregationSelector: DefaultAggregationSelector,
|
||||
cardinalityLimitSelector: defaultCardinalityLimitSelector,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
cfg = opt.applyManual(cfg)
|
||||
|
||||
+21
-11
@@ -26,17 +26,19 @@ const (
|
||||
|
||||
// periodicReaderConfig contains configuration options for a PeriodicReader.
|
||||
type periodicReaderConfig struct {
|
||||
interval time.Duration
|
||||
timeout time.Duration
|
||||
producers []Producer
|
||||
interval time.Duration
|
||||
timeout time.Duration
|
||||
producers []Producer
|
||||
cardinalityLimitSelector CardinalityLimitSelector
|
||||
}
|
||||
|
||||
// newPeriodicReaderConfig returns a periodicReaderConfig configured with
|
||||
// options.
|
||||
func newPeriodicReaderConfig(options []PeriodicReaderOption) periodicReaderConfig {
|
||||
c := periodicReaderConfig{
|
||||
interval: envDuration(envInterval, defaultInterval),
|
||||
timeout: envDuration(envTimeout, defaultTimeout),
|
||||
interval: envDuration(envInterval, defaultInterval),
|
||||
timeout: envDuration(envTimeout, defaultTimeout),
|
||||
cardinalityLimitSelector: defaultCardinalityLimitSelector,
|
||||
}
|
||||
for _, o := range options {
|
||||
c = o.applyPeriodic(c)
|
||||
@@ -111,12 +113,13 @@ func NewPeriodicReader(exporter Exporter, options ...PeriodicReaderOption) *Peri
|
||||
context.Background(),
|
||||
)
|
||||
r := &PeriodicReader{
|
||||
interval: conf.interval,
|
||||
timeout: conf.timeout,
|
||||
exporter: exporter,
|
||||
flushCh: make(chan chan error),
|
||||
cancel: cancel,
|
||||
done: make(chan struct{}),
|
||||
interval: conf.interval,
|
||||
timeout: conf.timeout,
|
||||
exporter: exporter,
|
||||
flushCh: make(chan chan error),
|
||||
cancel: cancel,
|
||||
done: make(chan struct{}),
|
||||
cardinalityLimitSelector: conf.cardinalityLimitSelector,
|
||||
rmPool: sync.Pool{
|
||||
New: func() any {
|
||||
return &metricdata.ResourceMetrics{}
|
||||
@@ -170,6 +173,8 @@ type PeriodicReader struct {
|
||||
|
||||
rmPool sync.Pool
|
||||
|
||||
cardinalityLimitSelector CardinalityLimitSelector
|
||||
|
||||
inst *observ.Instrumentation
|
||||
}
|
||||
|
||||
@@ -222,6 +227,11 @@ func (r *PeriodicReader) aggregation(
|
||||
return r.exporter.Aggregation(kind)
|
||||
}
|
||||
|
||||
// cardinalityLimit returns the cardinality limit for kind.
|
||||
func (r *PeriodicReader) cardinalityLimit(kind InstrumentKind) (int, bool) {
|
||||
return r.cardinalityLimitSelector(kind)
|
||||
}
|
||||
|
||||
// collectAndExport gather all metric data related to the periodicReader r from
|
||||
// the SDK and exports it with r's exporter.
|
||||
func (r *PeriodicReader) collectAndExport(ctx context.Context) error {
|
||||
|
||||
+15
-5
@@ -301,7 +301,7 @@ func (i *inserter[N]) addCallback(cback func(context.Context) error) {
|
||||
i.pipeline.callbacks = append(i.pipeline.callbacks, cback)
|
||||
}
|
||||
|
||||
var aggIDCount uint64
|
||||
var aggIDCount atomic.Uint64
|
||||
|
||||
// aggVal is the cached value in an aggregators cache.
|
||||
type aggVal[N int64 | float64] struct {
|
||||
@@ -395,9 +395,7 @@ func (i *inserter[N]) cachedAggregator(
|
||||
b.Filter = stream.AttributeFilter
|
||||
// A value less than or equal to zero will disable the aggregation
|
||||
// limits for the builder (an all the created aggregates).
|
||||
// cardinalityLimit will be 0 by default if unset (or
|
||||
// unrecognized input). Use that value directly.
|
||||
b.AggregationLimit = i.pipeline.cardinalityLimit
|
||||
b.AggregationLimit = i.getCardinalityLimit(kind)
|
||||
in, out, err := i.aggregateFunc(b, stream.Aggregation, kind)
|
||||
if err != nil {
|
||||
return aggVal[N]{0, nil, err}
|
||||
@@ -413,12 +411,24 @@ func (i *inserter[N]) cachedAggregator(
|
||||
unit: stream.Unit,
|
||||
compAgg: out,
|
||||
})
|
||||
id := atomic.AddUint64(&aggIDCount, 1)
|
||||
id := aggIDCount.Add(1)
|
||||
return aggVal[N]{id, in, err}
|
||||
})
|
||||
return cv.Measure, cv.ID, cv.Err
|
||||
}
|
||||
|
||||
// getCardinalityLimit returns the cardinality limit for the given instrument kind.
|
||||
// When the reader's selector returns fallback = true, the pipeline's global
|
||||
// limit is used, then the default if global is unset. When fallback is false,
|
||||
// the selector's limit is used (0 or less means unlimited).
|
||||
func (i *inserter[N]) getCardinalityLimit(kind InstrumentKind) int {
|
||||
limit, fallback := i.pipeline.reader.cardinalityLimit(kind)
|
||||
if fallback {
|
||||
return i.pipeline.cardinalityLimit
|
||||
}
|
||||
return limit
|
||||
}
|
||||
|
||||
// logConflict validates if an instrument with the same case-insensitive name
|
||||
// as id has already been created. If that instrument conflicts with id, a
|
||||
// warning is logged.
|
||||
|
||||
+58
@@ -59,6 +59,15 @@ type Reader interface {
|
||||
// Reader methods.
|
||||
aggregation(InstrumentKind) Aggregation // nolint:revive // import-shadow for method scoped by type.
|
||||
|
||||
// cardinalityLimit returns the cardinality limit for an instrument kind.
|
||||
// When fallback is true, the pipeline falls back to the provider's global limit.
|
||||
// When fallback is false, limit is used: 0 or less means no limit (unlimited),
|
||||
// and a positive value is the limit for that kind.
|
||||
//
|
||||
// This method needs to be concurrent safe with itself and all the other
|
||||
// Reader methods.
|
||||
cardinalityLimit(InstrumentKind) (limit int, fallback bool)
|
||||
|
||||
// Collect gathers and returns all metric data related to the Reader from
|
||||
// the SDK and stores it in rm. An error is returned if this is called
|
||||
// after Shutdown or if rm is nil.
|
||||
@@ -192,6 +201,25 @@ func DefaultAggregationSelector(ik InstrumentKind) Aggregation {
|
||||
panic("unknown instrument kind")
|
||||
}
|
||||
|
||||
// CardinalityLimitSelector selects the cardinality limit to use based on the
|
||||
// InstrumentKind. The cardinality limit is the maximum number of distinct
|
||||
// attribute sets that can be recorded for a single instrument.
|
||||
//
|
||||
// The selector returns (limit, fallback). When fallback is true, the pipeline
|
||||
// falls back to the provider's global cardinality limit.
|
||||
// When fallback is false, the limit is applied: a value of 0 or less means
|
||||
// no limit, and a positive value is the limit for that kind.
|
||||
// To avoid overriding the provider's global limit, return (0, true).
|
||||
type CardinalityLimitSelector func(InstrumentKind) (limit int, fallback bool)
|
||||
|
||||
// defaultCardinalityLimitSelector is the default CardinalityLimitSelector used
|
||||
// if WithCardinalityLimitSelector is not provided. It returns (0, true) for all
|
||||
// instrument kinds, allowing the pipeline to fall back to the provider's global
|
||||
// limit.
|
||||
func defaultCardinalityLimitSelector(_ InstrumentKind) (int, bool) {
|
||||
return 0, true
|
||||
}
|
||||
|
||||
// ReaderOption is an option which can be applied to manual or Periodic
|
||||
// readers.
|
||||
type ReaderOption interface {
|
||||
@@ -220,3 +248,33 @@ func (o producerOption) applyPeriodic(c periodicReaderConfig) periodicReaderConf
|
||||
c.producers = append(c.producers, o.p)
|
||||
return c
|
||||
}
|
||||
|
||||
// WithCardinalityLimitSelector sets the CardinalityLimitSelector a reader will
|
||||
// use to determine the cardinality limit for an instrument based on its kind.
|
||||
// If this option is not used, the reader will use the
|
||||
// defaultCardinalityLimitSelector.
|
||||
//
|
||||
// The selector should return (limit, false) to set a positive limit,
|
||||
// (0, false) to explicitly specify unlimited, or
|
||||
// (0, true) to fall back to the provider's global limit.
|
||||
//
|
||||
// See [CardinalityLimitSelector] for more details.
|
||||
func WithCardinalityLimitSelector(selector CardinalityLimitSelector) ReaderOption {
|
||||
return cardinalityLimitSelectorOption{selector: selector}
|
||||
}
|
||||
|
||||
type cardinalityLimitSelectorOption struct {
|
||||
selector CardinalityLimitSelector
|
||||
}
|
||||
|
||||
// applyManual returns a manualReaderConfig with option applied.
|
||||
func (o cardinalityLimitSelectorOption) applyManual(c manualReaderConfig) manualReaderConfig {
|
||||
c.cardinalityLimitSelector = o.selector
|
||||
return c
|
||||
}
|
||||
|
||||
// applyPeriodic returns a periodicReaderConfig with option applied.
|
||||
func (o cardinalityLimitSelectorOption) applyPeriodic(c periodicReaderConfig) periodicReaderConfig {
|
||||
c.cardinalityLimitSelector = o.selector
|
||||
return c
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"
|
||||
|
||||
// version is the current release version of the metric SDK in use.
|
||||
func version() string {
|
||||
return "1.42.0"
|
||||
return "1.43.0"
|
||||
}
|
||||
|
||||
+8
@@ -193,3 +193,11 @@ func WithContainer() Option {
|
||||
func WithContainerID() Option {
|
||||
return WithDetectors(cgroupContainerIDDetector{})
|
||||
}
|
||||
|
||||
// WithService adds all the Service attributes to the configured Resource.
|
||||
func WithService() Option {
|
||||
return WithDetectors(
|
||||
defaultServiceInstanceIDDetector{},
|
||||
defaultServiceNameDetector{},
|
||||
)
|
||||
}
|
||||
|
||||
+5
-5
@@ -31,19 +31,19 @@ type hostIDReaderBSD struct {
|
||||
readFile fileReader
|
||||
}
|
||||
|
||||
// read attempts to read the machine-id from /etc/hostid. If not found it will
|
||||
// execute `kenv -q smbios.system.uuid`. If neither location yields an id an
|
||||
// error will be returned.
|
||||
// read attempts to read the machine-id from /etc/hostid.
|
||||
// If not found it will execute: /bin/kenv -q smbios.system.uuid.
|
||||
// If neither location yields an id an error will be returned.
|
||||
func (r *hostIDReaderBSD) read() (string, error) {
|
||||
if result, err := r.readFile("/etc/hostid"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
if result, err := r.execCommand("kenv", "-q", "smbios.system.uuid"); err == nil {
|
||||
if result, err := r.execCommand("/bin/kenv", "-q", "smbios.system.uuid"); err == nil {
|
||||
return strings.TrimSpace(result), nil
|
||||
}
|
||||
|
||||
return "", errors.New("host id not found in: /etc/hostid or kenv")
|
||||
return "", errors.New("host id not found in: /etc/hostid or /bin/kenv")
|
||||
}
|
||||
|
||||
// hostIDReaderDarwin implements hostIDReader.
|
||||
|
||||
+17
-2
@@ -232,6 +232,15 @@ func Empty() *Resource {
|
||||
// Default returns an instance of Resource with a default
|
||||
// "service.name" and OpenTelemetrySDK attributes.
|
||||
func Default() *Resource {
|
||||
return DefaultWithContext(context.Background())
|
||||
}
|
||||
|
||||
// DefaultWithContext returns an instance of Resource with a default
|
||||
// "service.name" and OpenTelemetrySDK attributes.
|
||||
//
|
||||
// If the default resource has already been initialized, the provided ctx
|
||||
// is ignored and the cached resource is returned.
|
||||
func DefaultWithContext(ctx context.Context) *Resource {
|
||||
defaultResourceOnce.Do(func() {
|
||||
var err error
|
||||
defaultDetectors := []Detector{
|
||||
@@ -243,7 +252,7 @@ func Default() *Resource {
|
||||
defaultDetectors = append([]Detector{defaultServiceInstanceIDDetector{}}, defaultDetectors...)
|
||||
}
|
||||
defaultResource, err = Detect(
|
||||
context.Background(),
|
||||
ctx,
|
||||
defaultDetectors...,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -260,8 +269,14 @@ func Default() *Resource {
|
||||
// Environment returns an instance of Resource with attributes
|
||||
// extracted from the OTEL_RESOURCE_ATTRIBUTES environment variable.
|
||||
func Environment() *Resource {
|
||||
return EnvironmentWithContext(context.Background())
|
||||
}
|
||||
|
||||
// EnvironmentWithContext returns an instance of Resource with attributes
|
||||
// extracted from the OTEL_RESOURCE_ATTRIBUTES environment variable.
|
||||
func EnvironmentWithContext(ctx context.Context) *Resource {
|
||||
detector := &fromEnv{}
|
||||
resource, err := detector.Detect(context.Background())
|
||||
resource, err := detector.Detect(ctx)
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
|
||||
+3
-3
@@ -68,7 +68,7 @@ type batchSpanProcessor struct {
|
||||
o BatchSpanProcessorOptions
|
||||
|
||||
queue chan ReadOnlySpan
|
||||
dropped uint32
|
||||
dropped atomic.Uint32
|
||||
|
||||
inst *observ.BSP
|
||||
|
||||
@@ -293,7 +293,7 @@ func (bsp *batchSpanProcessor) exportSpans(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if l := len(bsp.batch); l > 0 {
|
||||
global.Debug("exporting spans", "count", len(bsp.batch), "total_dropped", atomic.LoadUint32(&bsp.dropped))
|
||||
global.Debug("exporting spans", "count", len(bsp.batch), "total_dropped", bsp.dropped.Load())
|
||||
if bsp.inst != nil {
|
||||
bsp.inst.Processed(ctx, int64(l))
|
||||
}
|
||||
@@ -421,7 +421,7 @@ func (bsp *batchSpanProcessor) enqueueDrop(ctx context.Context, sd ReadOnlySpan)
|
||||
case bsp.queue <- sd:
|
||||
return true
|
||||
default:
|
||||
atomic.AddUint32(&bsp.dropped, 1)
|
||||
bsp.dropped.Add(1)
|
||||
if bsp.inst != nil {
|
||||
bsp.inst.ProcessedQueueFull(ctx, 1)
|
||||
}
|
||||
|
||||
+8
@@ -55,6 +55,10 @@ func NewTracer() (Tracer, error) {
|
||||
func (t Tracer) Enabled() bool { return t.enabled }
|
||||
|
||||
func (t Tracer) SpanStarted(ctx context.Context, psc trace.SpanContext, span trace.Span) {
|
||||
if !t.started.Enabled(ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
key := spanStartedKey{
|
||||
parent: parentStateNoParent,
|
||||
sampling: samplingStateDrop,
|
||||
@@ -89,6 +93,10 @@ func (t Tracer) SpanEnded(ctx context.Context, span trace.Span) {
|
||||
}
|
||||
|
||||
func (t Tracer) spanLive(ctx context.Context, value int64, span trace.Span) {
|
||||
if !t.live.Enabled(ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
key := spanLiveKey{sampled: span.SpanContext().IsSampled()}
|
||||
opts := spanLiveOpts[key]
|
||||
t.live.Add(ctx, value, opts...)
|
||||
|
||||
+1
-8
@@ -303,14 +303,7 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error {
|
||||
sps.state.Do(func() {
|
||||
err = sps.sp.Shutdown(ctx)
|
||||
})
|
||||
if err != nil {
|
||||
if retErr == nil {
|
||||
retErr = err
|
||||
} else {
|
||||
// Poor man's list of errors
|
||||
retErr = fmt.Errorf("%w; %w", retErr, err)
|
||||
}
|
||||
}
|
||||
retErr = errors.Join(retErr, err)
|
||||
}
|
||||
p.spanProcessors.Store(&spanProcessorStates{})
|
||||
return retErr
|
||||
|
||||
+31
-5
@@ -69,17 +69,17 @@ type traceIDRatioSampler struct {
|
||||
}
|
||||
|
||||
func (ts traceIDRatioSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
psc := trace.SpanContextFromContext(p.ParentContext)
|
||||
state := trace.SpanContextFromContext(p.ParentContext).TraceState()
|
||||
x := binary.BigEndian.Uint64(p.TraceID[8:16]) >> 1
|
||||
if x < ts.traceIDUpperBound {
|
||||
return SamplingResult{
|
||||
Decision: RecordAndSample,
|
||||
Tracestate: psc.TraceState(),
|
||||
Tracestate: state,
|
||||
}
|
||||
}
|
||||
return SamplingResult{
|
||||
Decision: Drop,
|
||||
Tracestate: psc.TraceState(),
|
||||
Tracestate: state,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +94,20 @@ func (ts traceIDRatioSampler) Description() string {
|
||||
//
|
||||
//nolint:revive // revive complains about stutter of `trace.TraceIDRatioBased`
|
||||
func TraceIDRatioBased(fraction float64) Sampler {
|
||||
// Cannot use AlwaysSample() and NeverSample(), must return spec-compliant descriptions.
|
||||
// See https://opentelemetry.io/docs/specs/otel/trace/sdk/#traceidratiobased.
|
||||
if fraction >= 1 {
|
||||
return AlwaysSample()
|
||||
return predeterminedSampler{
|
||||
description: "TraceIDRatioBased{1}",
|
||||
decision: RecordAndSample,
|
||||
}
|
||||
}
|
||||
|
||||
if fraction <= 0 {
|
||||
fraction = 0
|
||||
return predeterminedSampler{
|
||||
description: "TraceIDRatioBased{0}",
|
||||
decision: Drop,
|
||||
}
|
||||
}
|
||||
|
||||
return &traceIDRatioSampler{
|
||||
@@ -118,6 +126,7 @@ func (alwaysOnSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
}
|
||||
|
||||
func (alwaysOnSampler) Description() string {
|
||||
// https://opentelemetry.io/docs/specs/otel/trace/sdk/#alwayson
|
||||
return "AlwaysOnSampler"
|
||||
}
|
||||
|
||||
@@ -139,6 +148,7 @@ func (alwaysOffSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
}
|
||||
|
||||
func (alwaysOffSampler) Description() string {
|
||||
// https://opentelemetry.io/docs/specs/otel/trace/sdk/#alwaysoff
|
||||
return "AlwaysOffSampler"
|
||||
}
|
||||
|
||||
@@ -147,6 +157,22 @@ func NeverSample() Sampler {
|
||||
return alwaysOffSampler{}
|
||||
}
|
||||
|
||||
type predeterminedSampler struct {
|
||||
description string
|
||||
decision SamplingDecision
|
||||
}
|
||||
|
||||
func (s predeterminedSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
return SamplingResult{
|
||||
Decision: s.decision,
|
||||
Tracestate: trace.SpanContextFromContext(p.ParentContext).TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s predeterminedSampler) Description() string {
|
||||
return s.description
|
||||
}
|
||||
|
||||
// ParentBased returns a sampler decorator which behaves differently,
|
||||
// based on the parent of the span. If the span has no parent,
|
||||
// the decorated sampler is used to make sampling decision. If the span has
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk"
|
||||
|
||||
// Version is the current release version of the OpenTelemetry SDK in use.
|
||||
func Version() string {
|
||||
return "1.42.0"
|
||||
return "1.43.0"
|
||||
}
|
||||
|
||||
+19
@@ -196,6 +196,20 @@ func (tf TraceFlags) WithSampled(sampled bool) TraceFlags { // nolint:revive //
|
||||
return tf &^ FlagsSampled
|
||||
}
|
||||
|
||||
// IsRandom reports whether the random bit is set in the TraceFlags.
|
||||
func (tf TraceFlags) IsRandom() bool {
|
||||
return tf&FlagsRandom == FlagsRandom
|
||||
}
|
||||
|
||||
// WithRandom sets the random bit in a new copy of the TraceFlags.
|
||||
func (tf TraceFlags) WithRandom(random bool) TraceFlags { // nolint:revive // random is not a control flag.
|
||||
if random {
|
||||
return tf | FlagsRandom
|
||||
}
|
||||
|
||||
return tf &^ FlagsRandom
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom marshal function to encode TraceFlags
|
||||
// as a hex string.
|
||||
func (tf TraceFlags) MarshalJSON() ([]byte, error) {
|
||||
@@ -322,6 +336,11 @@ func (sc SpanContext) IsSampled() bool {
|
||||
return sc.traceFlags.IsSampled()
|
||||
}
|
||||
|
||||
// IsRandom reports whether the random bit is set in the SpanContext's TraceFlags.
|
||||
func (sc SpanContext) IsRandom() bool {
|
||||
return sc.traceFlags.IsRandom()
|
||||
}
|
||||
|
||||
// WithTraceFlags returns a new SpanContext with the TraceFlags replaced.
|
||||
func (sc SpanContext) WithTraceFlags(flags TraceFlags) SpanContext {
|
||||
return SpanContext{
|
||||
|
||||
+1
-1
@@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel"
|
||||
|
||||
// Version is the current release version of OpenTelemetry in use.
|
||||
func Version() string {
|
||||
return "1.42.0"
|
||||
return "1.43.0"
|
||||
}
|
||||
|
||||
+6
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
module-sets:
|
||||
stable-v1:
|
||||
version: v1.42.0
|
||||
version: v1.43.0
|
||||
modules:
|
||||
- go.opentelemetry.io/otel
|
||||
- go.opentelemetry.io/otel/bridge/opencensus
|
||||
@@ -22,11 +22,11 @@ module-sets:
|
||||
- go.opentelemetry.io/otel/sdk/metric
|
||||
- go.opentelemetry.io/otel/trace
|
||||
experimental-metrics:
|
||||
version: v0.64.0
|
||||
version: v0.65.0
|
||||
modules:
|
||||
- go.opentelemetry.io/otel/exporters/prometheus
|
||||
experimental-logs:
|
||||
version: v0.18.0
|
||||
version: v0.19.0
|
||||
modules:
|
||||
- go.opentelemetry.io/otel/log
|
||||
- go.opentelemetry.io/otel/log/logtest
|
||||
@@ -64,3 +64,6 @@ modules:
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp:
|
||||
version-refs:
|
||||
- ./internal/version.go
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog:
|
||||
version-refs:
|
||||
- ./internal/version.go
|
||||
|
||||
+98
-47
@@ -53,6 +53,7 @@ type AnyValue struct {
|
||||
// *AnyValue_ArrayValue
|
||||
// *AnyValue_KvlistValue
|
||||
// *AnyValue_BytesValue
|
||||
// *AnyValue_StringValueStrindex
|
||||
Value isAnyValue_Value `protobuf_oneof:"value"`
|
||||
}
|
||||
|
||||
@@ -144,6 +145,13 @@ func (x *AnyValue) GetBytesValue() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AnyValue) GetStringValueStrindex() int32 {
|
||||
if x, ok := x.GetValue().(*AnyValue_StringValueStrindex); ok {
|
||||
return x.StringValueStrindex
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type isAnyValue_Value interface {
|
||||
isAnyValue_Value()
|
||||
}
|
||||
@@ -176,6 +184,20 @@ type AnyValue_BytesValue struct {
|
||||
BytesValue []byte `protobuf:"bytes,7,opt,name=bytes_value,json=bytesValue,proto3,oneof"`
|
||||
}
|
||||
|
||||
type AnyValue_StringValueStrindex struct {
|
||||
// Reference to the string value in ProfilesDictionary.string_table.
|
||||
//
|
||||
// Note: This is currently used exclusively in the Profiling signal.
|
||||
// Implementers of OTLP receivers for signals other than Profiling should
|
||||
// treat the presence of this value as a non-fatal issue.
|
||||
// Log an error or warning indicating an unexpected field intended for the
|
||||
// Profiling signal and process the data as if this value were absent or
|
||||
// empty, ignoring its semantic content for the non-Profiling signal.
|
||||
//
|
||||
// Status: [Development]
|
||||
StringValueStrindex int32 `protobuf:"varint,8,opt,name=string_value_strindex,json=stringValueStrindex,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*AnyValue_StringValue) isAnyValue_Value() {}
|
||||
|
||||
func (*AnyValue_BoolValue) isAnyValue_Value() {}
|
||||
@@ -190,6 +212,8 @@ func (*AnyValue_KvlistValue) isAnyValue_Value() {}
|
||||
|
||||
func (*AnyValue_BytesValue) isAnyValue_Value() {}
|
||||
|
||||
func (*AnyValue_StringValueStrindex) isAnyValue_Value() {}
|
||||
|
||||
// ArrayValue is a list of AnyValue messages. We need ArrayValue as a message
|
||||
// since oneof in AnyValue does not allow repeated fields.
|
||||
type ArrayValue struct {
|
||||
@@ -306,9 +330,22 @@ type KeyValue struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// The key name of the pair.
|
||||
// key_ref MUST NOT be set if key is used.
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
// The value of the pair.
|
||||
Value *AnyValue `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
// Reference to the string key in ProfilesDictionary.string_table.
|
||||
// key MUST NOT be set if key_strindex is used.
|
||||
//
|
||||
// Note: This is currently used exclusively in the Profiling signal.
|
||||
// Implementers of OTLP receivers for signals other than Profiling should
|
||||
// treat the presence of this key as a non-fatal issue.
|
||||
// Log an error or warning indicating an unexpected field intended for the
|
||||
// Profiling signal and process the data as if this value were absent or
|
||||
// empty, ignoring its semantic content for the non-Profiling signal.
|
||||
//
|
||||
// Status: [Development]
|
||||
KeyStrindex int32 `protobuf:"varint,3,opt,name=key_strindex,json=keyStrindex,proto3" json:"key_strindex,omitempty"`
|
||||
}
|
||||
|
||||
func (x *KeyValue) Reset() {
|
||||
@@ -357,6 +394,13 @@ func (x *KeyValue) GetValue() *AnyValue {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KeyValue) GetKeyStrindex() int32 {
|
||||
if x != nil {
|
||||
return x.KeyStrindex
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InstrumentationScope is a message representing the instrumentation scope information
|
||||
// such as the fully qualified name and version.
|
||||
type InstrumentationScope struct {
|
||||
@@ -543,7 +587,7 @@ var file_opentelemetry_proto_common_v1_common_proto_rawDesc = []byte{
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x22, 0xe0, 0x02, 0x0a, 0x08,
|
||||
0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x22, 0x96, 0x03, 0x0a, 0x08,
|
||||
0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a,
|
||||
@@ -565,52 +609,58 @@ var file_opentelemetry_proto_common_v1_common_proto_rawDesc = []byte{
|
||||
0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6b, 0x76, 0x6c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d,
|
||||
0x0a, 0x0a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x06,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f,
|
||||
0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x79,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x4f, 0x0a,
|
||||
0x0c, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3f, 0x0a,
|
||||
0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65,
|
||||
0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x5b,
|
||||
0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, 0x79, 0x56,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x14,
|
||||
0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c,
|
||||
0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52,
|
||||
0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64,
|
||||
0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65,
|
||||
0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64,
|
||||
0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82, 0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79,
|
||||
0x52, 0x65, 0x66, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x75, 0x72,
|
||||
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x55,
|
||||
0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x64, 0x5f, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12,
|
||||
0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b,
|
||||
0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72,
|
||||
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x42, 0x7b, 0x0a, 0x20, 0x69, 0x6f,
|
||||
0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0b,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67,
|
||||
0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e,
|
||||
0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x74, 0x6c, 0x70, 0x2f, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0xaa, 0x02, 0x1d, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65,
|
||||
0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x15, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x13, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x07, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x22, 0x4d, 0x0a, 0x0a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x56, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74,
|
||||
0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x0c, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65,
|
||||
0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x73, 0x22, 0x7e, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72,
|
||||
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x41, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6b, 0x65, 0x79, 0x53, 0x74, 0x72, 0x69,
|
||||
0x6e, 0x64, 0x65, 0x78, 0x22, 0xc7, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d,
|
||||
0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0a, 0x61,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
|
||||
0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x82,
|
||||
0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x66, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x74,
|
||||
0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||
0x17, 0x0a, 0x07, 0x69, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
|
||||
0x52, 0x06, 0x69, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03,
|
||||
0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b,
|
||||
0x65, 0x79, 0x73, 0x42, 0x7b, 0x0a, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65,
|
||||
0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74,
|
||||
0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x2f, 0x6f, 0x74, 0x6c, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31,
|
||||
0xaa, 0x02, 0x1d, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79,
|
||||
0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x56, 0x31,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -735,6 +785,7 @@ func file_opentelemetry_proto_common_v1_common_proto_init() {
|
||||
(*AnyValue_ArrayValue)(nil),
|
||||
(*AnyValue_KvlistValue)(nil),
|
||||
(*AnyValue_BytesValue)(nil),
|
||||
(*AnyValue_StringValueStrindex)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
|
||||
+10
-3
@@ -6,6 +6,7 @@ package hpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// headerFieldTable implements a list of HeaderFields.
|
||||
@@ -54,10 +55,16 @@ func (t *headerFieldTable) len() int {
|
||||
|
||||
// addEntry adds a new entry.
|
||||
func (t *headerFieldTable) addEntry(f HeaderField) {
|
||||
// Prevent f from escaping to the heap.
|
||||
f2 := HeaderField{
|
||||
Name: strings.Clone(f.Name),
|
||||
Value: strings.Clone(f.Value),
|
||||
Sensitive: f.Sensitive,
|
||||
}
|
||||
id := uint64(t.len()) + t.evictCount + 1
|
||||
t.byName[f.Name] = id
|
||||
t.byNameValue[pairNameValue{f.Name, f.Value}] = id
|
||||
t.ents = append(t.ents, f)
|
||||
t.byName[f2.Name] = id
|
||||
t.byNameValue[pairNameValue{f2.Name, f2.Value}] = id
|
||||
t.ents = append(t.ents, f2)
|
||||
}
|
||||
|
||||
// evictOldest evicts the n oldest entries in the table.
|
||||
|
||||
+3
-6
@@ -718,9 +718,6 @@ func canRetryError(err error) bool {
|
||||
}
|
||||
|
||||
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
|
||||
if t.transportTestHooks != nil {
|
||||
return t.newClientConn(nil, singleUse, nil)
|
||||
}
|
||||
host, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -2861,6 +2858,9 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
||||
|
||||
var seenMaxConcurrentStreams bool
|
||||
err := f.ForeachSetting(func(s Setting) error {
|
||||
if err := s.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch s.ID {
|
||||
case SettingMaxFrameSize:
|
||||
cc.maxFrameSize = s.Val
|
||||
@@ -2892,9 +2892,6 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
||||
cc.henc.SetMaxDynamicTableSize(s.Val)
|
||||
cc.peerMaxHeaderTableSize = s.Val
|
||||
case SettingEnableConnectProtocol:
|
||||
if err := s.Valid(); err != nil {
|
||||
return err
|
||||
}
|
||||
// If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL,
|
||||
// we require that it do so in the first SETTINGS frame.
|
||||
//
|
||||
|
||||
+1
-36
@@ -163,42 +163,7 @@ func (p *Proc) Addr() uintptr {
|
||||
// (according to the semantics of the specific function being called) before consulting
|
||||
// the error. The error will be guaranteed to contain windows.Errno.
|
||||
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
switch len(a) {
|
||||
case 0:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
|
||||
case 1:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
|
||||
case 2:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
|
||||
case 3:
|
||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
|
||||
case 4:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
|
||||
case 5:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
|
||||
case 6:
|
||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
|
||||
case 7:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
|
||||
case 8:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
|
||||
case 9:
|
||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
|
||||
case 10:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
|
||||
case 11:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
|
||||
case 12:
|
||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
|
||||
case 13:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
|
||||
case 14:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
|
||||
case 15:
|
||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
|
||||
default:
|
||||
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
|
||||
}
|
||||
return syscall.SyscallN(p.Addr(), a...)
|
||||
}
|
||||
|
||||
// A LazyDLL implements access to a single DLL.
|
||||
|
||||
+5
-1
@@ -1438,13 +1438,17 @@ func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformati
|
||||
}
|
||||
|
||||
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
|
||||
// descriptor result on the Go heap.
|
||||
// descriptor result on the Go heap. The security descriptor might be nil, even when err is nil, if the object exists
|
||||
// but has no security descriptor.
|
||||
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||
var winHeapSD *SECURITY_DESCRIPTOR
|
||||
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if winHeapSD == nil {
|
||||
return nil, nil
|
||||
}
|
||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2025 Google LLC
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright 2025 Google LLC
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -957,17 +957,17 @@ type BadRequest_FieldViolation struct {
|
||||
// In this example, in proto `field` could take one of the following values:
|
||||
//
|
||||
// - `full_name` for a violation in the `full_name` value
|
||||
// - `email_addresses[1].email` for a violation in the `email` field of the
|
||||
// - `email_addresses[0].email` for a violation in the `email` field of the
|
||||
// first `email_addresses` message
|
||||
// - `email_addresses[3].type[2]` for a violation in the second `type`
|
||||
// - `email_addresses[2].type[1]` for a violation in the second `type`
|
||||
// value in the third `email_addresses` message.
|
||||
//
|
||||
// In JSON, the same values are represented as:
|
||||
//
|
||||
// - `fullName` for a violation in the `fullName` value
|
||||
// - `emailAddresses[1].email` for a violation in the `email` field of the
|
||||
// - `emailAddresses[0].email` for a violation in the `email` field of the
|
||||
// first `emailAddresses` message
|
||||
// - `emailAddresses[3].type[2]` for a violation in the second `type`
|
||||
// - `emailAddresses[2].type[1]` for a violation in the second `type`
|
||||
// value in the third `emailAddresses` message.
|
||||
Field string `protobuf:"bytes,1,opt,name=field,proto3" json:"field,omitempty"`
|
||||
// A description of why the request element is bad.
|
||||
|
||||
+3
-4
@@ -1,4 +1,4 @@
|
||||
// Copyright 2025 Google LLC
|
||||
// Copyright 2026 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -127,14 +127,13 @@ var file_google_rpc_status_proto_rawDesc = []byte{
|
||||
0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61,
|
||||
0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52,
|
||||
0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x61, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
|
||||
0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x5e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x42, 0x0b, 0x53, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73,
|
||||
0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
0x75, 0x73, 0xa2, 0x02, 0x03, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+55
-22
@@ -27,6 +27,8 @@ package attributes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"iter"
|
||||
"maps"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -37,37 +39,46 @@ import (
|
||||
// any) bool', it will be called by (*Attributes).Equal to determine whether
|
||||
// two values with the same key should be considered equal.
|
||||
type Attributes struct {
|
||||
m map[any]any
|
||||
parent *Attributes
|
||||
key, value any
|
||||
}
|
||||
|
||||
// New returns a new Attributes containing the key/value pair.
|
||||
func New(key, value any) *Attributes {
|
||||
return &Attributes{m: map[any]any{key: value}}
|
||||
return &Attributes{
|
||||
key: key,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// WithValue returns a new Attributes containing the previous keys and values
|
||||
// and the new key/value pair. If the same key appears multiple times, the
|
||||
// last value overwrites all previous values for that key. To remove an
|
||||
// existing key, use a nil value. value should not be modified later.
|
||||
// last value overwrites all previous values for that key. value should not be
|
||||
// modified later.
|
||||
//
|
||||
// Note that Attributes do not support deletion. Avoid using untyped nil values.
|
||||
// Since the Value method returns an untyped nil when a key is absent, it is
|
||||
// impossible to distinguish between a missing key and a key explicitly set to
|
||||
// an untyped nil. If you need to represent a value being unset, consider
|
||||
// storing a specific sentinel type or a wrapper struct with a boolean field
|
||||
// indicating presence.
|
||||
func (a *Attributes) WithValue(key, value any) *Attributes {
|
||||
if a == nil {
|
||||
return New(key, value)
|
||||
return &Attributes{
|
||||
parent: a,
|
||||
key: key,
|
||||
value: value,
|
||||
}
|
||||
n := &Attributes{m: make(map[any]any, len(a.m)+1)}
|
||||
for k, v := range a.m {
|
||||
n.m[k] = v
|
||||
}
|
||||
n.m[key] = value
|
||||
return n
|
||||
}
|
||||
|
||||
// Value returns the value associated with these attributes for key, or nil if
|
||||
// no value is associated with key. The returned value should not be modified.
|
||||
func (a *Attributes) Value(key any) any {
|
||||
if a == nil {
|
||||
return nil
|
||||
for cur := a; cur != nil; cur = cur.parent {
|
||||
if cur.key == key {
|
||||
return cur.value
|
||||
}
|
||||
}
|
||||
return a.m[key]
|
||||
return nil
|
||||
}
|
||||
|
||||
// Equal returns whether a and o are equivalent. If 'Equal(o any) bool' is
|
||||
@@ -83,11 +94,15 @@ func (a *Attributes) Equal(o *Attributes) bool {
|
||||
if a == nil || o == nil {
|
||||
return false
|
||||
}
|
||||
if len(a.m) != len(o.m) {
|
||||
return false
|
||||
if a == o {
|
||||
return true
|
||||
}
|
||||
for k, v := range a.m {
|
||||
ov, ok := o.m[k]
|
||||
m := maps.Collect(o.all())
|
||||
lenA := 0
|
||||
|
||||
for k, v := range a.all() {
|
||||
lenA++
|
||||
ov, ok := m[k]
|
||||
if !ok {
|
||||
// o missing element of a
|
||||
return false
|
||||
@@ -101,7 +116,7 @@ func (a *Attributes) Equal(o *Attributes) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return lenA == len(m)
|
||||
}
|
||||
|
||||
// String prints the attribute map. If any key or values throughout the map
|
||||
@@ -110,11 +125,11 @@ func (a *Attributes) String() string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("{")
|
||||
first := true
|
||||
for k, v := range a.m {
|
||||
for k, v := range a.all() {
|
||||
if !first {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%q: %q ", str(k), str(v)))
|
||||
fmt.Fprintf(&sb, "%q: %q ", str(k), str(v))
|
||||
first = false
|
||||
}
|
||||
sb.WriteString("}")
|
||||
@@ -139,3 +154,21 @@ func str(x any) (s string) {
|
||||
func (a *Attributes) MarshalJSON() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
|
||||
// all returns an iterator that yields all key-value pairs in the Attributes
|
||||
// chain. If a key appears multiple times, only the most recently added value
|
||||
// is yielded.
|
||||
func (a *Attributes) all() iter.Seq2[any, any] {
|
||||
return func(yield func(any, any) bool) {
|
||||
seen := map[any]bool{}
|
||||
for cur := a; cur != nil; cur = cur.parent {
|
||||
if seen[cur.key] {
|
||||
continue
|
||||
}
|
||||
if !yield(cur.key, cur.value) {
|
||||
return
|
||||
}
|
||||
seen[cur.key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-15
@@ -33,6 +33,7 @@ import (
|
||||
estats "google.golang.org/grpc/experimental/stats"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/internal"
|
||||
"google.golang.org/grpc/internal/envconfig"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/resolver"
|
||||
"google.golang.org/grpc/serviceconfig"
|
||||
@@ -46,8 +47,8 @@ var (
|
||||
)
|
||||
|
||||
// Register registers the balancer builder to the balancer map. b.Name
|
||||
// (lowercased) will be used as the name registered with this builder. If the
|
||||
// Builder implements ConfigParser, ParseConfig will be called when new service
|
||||
// will be used as the name registered with this builder. If the Builder
|
||||
// implements ConfigParser, ParseConfig will be called when new service
|
||||
// configs are received by the resolver, and the result will be provided to the
|
||||
// Balancer in UpdateClientConnState.
|
||||
//
|
||||
@@ -55,12 +56,12 @@ var (
|
||||
// an init() function), and is not thread-safe. If multiple Balancers are
|
||||
// registered with the same name, the one registered last will take effect.
|
||||
func Register(b Builder) {
|
||||
name := strings.ToLower(b.Name())
|
||||
if name != b.Name() {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon", b.Name())
|
||||
name := b.Name()
|
||||
if !envconfig.CaseSensitiveBalancerRegistries {
|
||||
name = strings.ToLower(name)
|
||||
if name != b.Name() {
|
||||
logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", b.Name())
|
||||
}
|
||||
}
|
||||
m[name] = b
|
||||
}
|
||||
@@ -78,16 +79,17 @@ func init() {
|
||||
}
|
||||
|
||||
// Get returns the resolver builder registered with the given name.
|
||||
// Note that the compare is done in a case-insensitive fashion.
|
||||
// Note that the compare is done in a case-sensitive fashion.
|
||||
// If no builder is register with the name, nil will be returned.
|
||||
func Get(name string) Builder {
|
||||
if strings.ToLower(name) != name {
|
||||
// TODO: Skip the use of strings.ToLower() to index the map after v1.59
|
||||
// is released to switch to case sensitive balancer registry. Also,
|
||||
// remove this warning and update the docstrings for Register and Get.
|
||||
logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon", name)
|
||||
if !envconfig.CaseSensitiveBalancerRegistries {
|
||||
lowerName := strings.ToLower(name)
|
||||
if lowerName != name {
|
||||
logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", name)
|
||||
}
|
||||
name = lowerName
|
||||
}
|
||||
if b, ok := m[strings.ToLower(name)]; ok {
|
||||
if b, ok := m[name]; ok {
|
||||
return b
|
||||
}
|
||||
return nil
|
||||
|
||||
+2
-4
@@ -121,8 +121,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
|
||||
sc.Connect()
|
||||
}
|
||||
}
|
||||
for _, a := range b.subConns.Keys() {
|
||||
sc, _ := b.subConns.Get(a)
|
||||
for a, sc := range b.subConns.All() {
|
||||
// a was removed by resolver.
|
||||
if _, ok := addrsSet.Get(a); !ok {
|
||||
sc.Shutdown()
|
||||
@@ -171,8 +170,7 @@ func (b *baseBalancer) regeneratePicker() {
|
||||
readySCs := make(map[balancer.SubConn]SubConnInfo)
|
||||
|
||||
// Filter out all ready SCs from full subConn map.
|
||||
for _, addr := range b.subConns.Keys() {
|
||||
sc, _ := b.subConns.Get(addr)
|
||||
for addr, sc := range b.subConns.All() {
|
||||
if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
|
||||
readySCs[sc] = SubConnInfo{Address: addr}
|
||||
}
|
||||
|
||||
+5
-6
@@ -187,8 +187,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState
|
||||
}
|
||||
}
|
||||
// Delete old children that are no longer present.
|
||||
for _, e := range children.Keys() {
|
||||
child, _ := children.Get(e)
|
||||
for e, child := range children.All() {
|
||||
if _, ok := newChildren.Get(e); !ok {
|
||||
child.closeLocked()
|
||||
}
|
||||
@@ -212,7 +211,7 @@ func (es *endpointSharding) ResolverError(err error) {
|
||||
es.updateState()
|
||||
}()
|
||||
children := es.children.Load()
|
||||
for _, child := range children.Values() {
|
||||
for _, child := range children.All() {
|
||||
child.resolverErrorLocked(err)
|
||||
}
|
||||
}
|
||||
@@ -225,7 +224,7 @@ func (es *endpointSharding) Close() {
|
||||
es.childMu.Lock()
|
||||
defer es.childMu.Unlock()
|
||||
children := es.children.Load()
|
||||
for _, child := range children.Values() {
|
||||
for _, child := range children.All() {
|
||||
child.closeLocked()
|
||||
}
|
||||
}
|
||||
@@ -233,7 +232,7 @@ func (es *endpointSharding) Close() {
|
||||
func (es *endpointSharding) ExitIdle() {
|
||||
es.childMu.Lock()
|
||||
defer es.childMu.Unlock()
|
||||
for _, bw := range es.children.Load().Values() {
|
||||
for _, bw := range es.children.Load().All() {
|
||||
if !bw.isClosed {
|
||||
bw.child.ExitIdle()
|
||||
}
|
||||
@@ -255,7 +254,7 @@ func (es *endpointSharding) updateState() {
|
||||
children := es.children.Load()
|
||||
childStates := make([]ChildState, 0, children.Len())
|
||||
|
||||
for _, child := range children.Values() {
|
||||
for _, child := range children.All() {
|
||||
childState := child.childState
|
||||
childStates = append(childStates, childState)
|
||||
childPicker := childState.State.Picker
|
||||
|
||||
+6
-6
@@ -399,14 +399,14 @@ func (b *pickfirstBalancer) startFirstPassLocked() {
|
||||
b.firstPass = true
|
||||
b.numTF = 0
|
||||
// Reset the connection attempt record for existing SubConns.
|
||||
for _, sd := range b.subConns.Values() {
|
||||
for _, sd := range b.subConns.All() {
|
||||
sd.connectionFailedInFirstPass = false
|
||||
}
|
||||
b.requestConnectionLocked()
|
||||
}
|
||||
|
||||
func (b *pickfirstBalancer) closeSubConnsLocked() {
|
||||
for _, sd := range b.subConns.Values() {
|
||||
for _, sd := range b.subConns.All() {
|
||||
sd.subConn.Shutdown()
|
||||
}
|
||||
b.subConns = resolver.NewAddressMapV2[*scData]()
|
||||
@@ -506,7 +506,7 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address)
|
||||
newAddrsMap.Set(addr, true)
|
||||
}
|
||||
|
||||
for _, oldAddr := range b.subConns.Keys() {
|
||||
for oldAddr := range b.subConns.All() {
|
||||
if _, ok := newAddrsMap.Get(oldAddr); ok {
|
||||
continue
|
||||
}
|
||||
@@ -520,7 +520,7 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address)
|
||||
// becomes ready, which means that all other subConn must be shutdown.
|
||||
func (b *pickfirstBalancer) shutdownRemainingLocked(selected *scData) {
|
||||
b.cancelConnectionTimer()
|
||||
for _, sd := range b.subConns.Values() {
|
||||
for _, sd := range b.subConns.All() {
|
||||
if sd.subConn != selected.subConn {
|
||||
sd.subConn.Shutdown()
|
||||
}
|
||||
@@ -771,7 +771,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) {
|
||||
}
|
||||
// Connect() has been called on all the SubConns. The first pass can be
|
||||
// ended if all the SubConns have reported a failure.
|
||||
for _, sd := range b.subConns.Values() {
|
||||
for _, sd := range b.subConns.All() {
|
||||
if !sd.connectionFailedInFirstPass {
|
||||
return
|
||||
}
|
||||
@@ -782,7 +782,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) {
|
||||
Picker: &picker{err: lastErr},
|
||||
})
|
||||
// Start re-connecting all the SubConns that are already in IDLE.
|
||||
for _, sd := range b.subConns.Values() {
|
||||
for _, sd := range b.subConns.All() {
|
||||
if sd.rawConnectivityState == connectivity.Idle {
|
||||
sd.subConn.Connect()
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.10
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc v5.27.1
|
||||
// source: grpc/binlog/v1/binarylog.proto
|
||||
|
||||
|
||||
+8
-10
@@ -22,7 +22,6 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
@@ -52,22 +51,21 @@ func (t TLSInfo) AuthType() string {
|
||||
}
|
||||
|
||||
// ValidateAuthority validates the provided authority being used to override the
|
||||
// :authority header by verifying it against the peer certificates. It returns a
|
||||
// :authority header by verifying it against the peer certificate. It returns a
|
||||
// non-nil error if the validation fails.
|
||||
func (t TLSInfo) ValidateAuthority(authority string) error {
|
||||
var errs []error
|
||||
host, _, err := net.SplitHostPort(authority)
|
||||
if err != nil {
|
||||
host = authority
|
||||
}
|
||||
for _, cert := range t.State.PeerCertificates {
|
||||
var err error
|
||||
if err = cert.VerifyHostname(host); err == nil {
|
||||
return nil
|
||||
}
|
||||
errs = append(errs, err)
|
||||
|
||||
// Verify authority against the leaf certificate.
|
||||
if len(t.State.PeerCertificates) == 0 {
|
||||
// This is not expected to happen as the TLS handshake has already
|
||||
// completed and should have populated PeerCertificates.
|
||||
return fmt.Errorf("credentials: no peer certificates found to verify authority %q", host)
|
||||
}
|
||||
return fmt.Errorf("credentials: invalid authority %q: %v", authority, errors.Join(errs...))
|
||||
return t.State.PeerCertificates[0].VerifyHostname(host)
|
||||
}
|
||||
|
||||
// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
|
||||
|
||||
+5
-4
@@ -705,10 +705,11 @@ func WithDisableHealthCheck() DialOption {
|
||||
func defaultDialOptions() dialOptions {
|
||||
return dialOptions{
|
||||
copts: transport.ConnectOptions{
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
UserAgent: grpcUA,
|
||||
BufferPool: mem.DefaultBufferPool(),
|
||||
ReadBufferSize: defaultReadBufSize,
|
||||
WriteBufferSize: defaultWriteBufSize,
|
||||
SharedWriteBuffer: true,
|
||||
UserAgent: grpcUA,
|
||||
BufferPool: mem.DefaultBufferPool(),
|
||||
},
|
||||
bs: internalbackoff.DefaultExponential,
|
||||
idleTimeout: 30 * time.Minute,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user